capataz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0c29c01bcf811102a7b55b2cb078411516f6e5ae
4
+ data.tar.gz: 366911255ca5df4e56264b9d5855bf81a470fd38
5
+ SHA512:
6
+ metadata.gz: b24a102e5f3cca7f062b3f963a58fefbb0df89ff9c3140f3410b8b6f3475e21671a3326b1087642169e8289abc7916a3cf9e1d4114e1528d921dad6a9e207992
7
+ data.tar.gz: 287a8b838427b32b8cd829865609b37c2a2e988762ce4e69856bbe78f6c87832cc4c038c408198303a8a7ca08afb5239541de172888475ed64b202b9ba6393f6
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'parser'
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Maikel Arcia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,89 @@
1
+ # Capataz
2
+
3
+ Provides Ruby code execution control by defining rules for syntax and runtime behavior.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'capataz'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install capataz
20
+
21
+ ## Usage
22
+
23
+ Take for example the following Ruby code:
24
+
25
+ ```ruby
26
+ class A
27
+ attr_reader :value, :secret_value
28
+ def initialize
29
+ @value = rand(10)
30
+ @secret_value = rand(value)
31
+ end
32
+ end
33
+
34
+ class B < A; end
35
+ ```
36
+
37
+ So you can configure your code syntax and runtime rules
38
+ ```ruby
39
+ Capataz.config do
40
+
41
+ deny_declarations_of :module, :class
42
+
43
+ deny_invoke_of :constantize
44
+
45
+ allowed_constants A
46
+
47
+ deny_for A, :secret_value
48
+ end
49
+ ```
50
+
51
+ And then you can control your Ruby code execution by evaluating it with `Capataz`
52
+
53
+ ```ruby
54
+ Capataz.eval <<-RUBY
55
+ class C
56
+ end
57
+ RUBY #ERROR: can not define classes
58
+
59
+ Capataz.eval <<-RUBY
60
+ B.new
61
+ RUBY #ERROR: Illegal access to constant B
62
+
63
+ Capataz.eval <<-RUBY
64
+ 'B'.constantize.new
65
+ RUBY #ERROR: invoking method constantize is not allowed
66
+
67
+ Capataz.eval <<-RUBY
68
+ A.new.value
69
+ RUBY # 5 (a random value)
70
+
71
+ Capataz.eval <<-RUBY
72
+ A.new.secret_value
73
+ RUBY #ERROR: undefined method secret_value for #<A:0x000000022e7960>
74
+ ```
75
+
76
+
77
+ ## Development
78
+
79
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
80
+
81
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
82
+
83
+ ## Contributing
84
+
85
+ 1. Fork it ( https://github.com/macarci/capataz/fork )
86
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
87
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
88
+ 4. Push to the branch (`git push origin my-new-feature`)
89
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'capataz'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'capataz/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'capataz'
8
+ spec.version = Capataz::VERSION
9
+ spec.authors = ['Maikel Arcia']
10
+ spec.email = ['macarci@gmail.com']
11
+
12
+ spec.summary = %q{Provides Ruby code execution control by defining rules for syntax and runtime behavior.}
13
+ spec.homepage = 'https://github.com/macarci/capataz'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.8'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+
24
+ spec.add_runtime_dependency 'parser'
25
+ end
@@ -0,0 +1,207 @@
1
+ require 'capataz/version'
2
+ require 'parser/current'
3
+ require 'capataz/core_ext'
4
+ require 'capataz/proxy'
5
+ require 'capataz/rewriter'
6
+
7
+ module Capataz
8
+
9
+ class << self
10
+
11
+ def eval(string, *binding_filename_lineno)
12
+ string = rewrite(string)
13
+ super
14
+ end
15
+
16
+ def disable(*args)
17
+ @disable = args.first.to_s.to_i.to_b
18
+ end
19
+
20
+ def disable?
21
+ @disable
22
+ end
23
+
24
+ def deny_declarations_of(*symbols)
25
+ symbol_array_store(:denied_declarations, symbols)
26
+ end
27
+
28
+ def deny_invoke_of(*methods)
29
+ symbol_array_store(:denied_methods, methods)
30
+ end
31
+
32
+ def allowed_constants(*constants)
33
+ set = @config[:allowed_constants]
34
+ constants = [constants] unless constants.is_a?(Enumerable)
35
+ constants << Capataz unless constants.include?(Capataz)
36
+ constants.each { |constant| set << constant }
37
+ end
38
+
39
+ def allow_on(objs, *methods)
40
+ store_options(:instances, :allow, objs, methods)
41
+ end
42
+
43
+ def deny_on(objs, *methods)
44
+ store_options(:instances, :deny, objs, methods)
45
+ end
46
+
47
+ def allow_for(types, *options)
48
+ store_options(:modules, :allow, types, options) { |type| type.is_a?(Module) }
49
+ end
50
+
51
+ def deny_for(types, *options)
52
+ store_options(:modules, :deny, types, options) { |type| type.is_a?(Module) }
53
+ end
54
+
55
+ def config(&block)
56
+ @config ||=
57
+ {
58
+ denied_declarations: Set.new,
59
+ allowed_constants: Set.new,
60
+ denied_methods: Set.new,
61
+ instances: {},
62
+ modules: {}
63
+ }
64
+ class_eval(&block) if block
65
+ @config
66
+ end
67
+
68
+ def instance_response_to?(instance, *args)
69
+ fail ArgumentError if args.length == 0
70
+ method = args[0].is_a?(Symbol) ? args[0] : args[0].to_s.to_sym
71
+ return false if @config[:denied_methods].include?(method)
72
+ if (options = @config[:instances][instance])
73
+ return false unless allowed_method?(options, instance, method)
74
+ else
75
+ @config[:modules].each do |type, opts|
76
+ if instance.is_a?(type)
77
+ return false unless allowed_method?(opts, instance, method)
78
+ end
79
+ end
80
+ end
81
+ instance.respond_to?(*args)
82
+ end
83
+
84
+ def allows_invocation_of(method)
85
+ method = method.to_s.to_sym unless method.is_a?(Symbol)
86
+ return false if @config[:denied_methods].include?(method)
87
+ true
88
+ end
89
+
90
+ def allowed_constant?(const)
91
+ (set = @config[:allowed_constants]) && set.include?(const)
92
+ end
93
+
94
+ def can_declare?(symbol)
95
+ (set = @config[:denied_declarations]).empty? || !set.include?(symbol)
96
+ end
97
+
98
+ def validate(code)
99
+ errors = []
100
+ begin
101
+ buffer = Parser::Source::Buffer.new('code')
102
+ buffer.source = code
103
+ Capataz::Rewriter.new(errors: errors).rewrite(buffer, Parser::CurrentRuby.new.parse(buffer))
104
+ rescue => ex
105
+ errors << ex.message
106
+ end
107
+ errors
108
+ end
109
+
110
+ def rewrite(code, options = {})
111
+ return code if Capataz.disable?
112
+ options ||= {}
113
+ options[:halt_on_error] = true if options[:halt_on_error].nil?
114
+ if (locals = options[:locals])
115
+ locals = [locals] unless locals.is_a?(Enumerable)
116
+ locals.each { |local| code = "#{local} ||= nil\r\n" + code }
117
+ end
118
+ buffer = Parser::Source::Buffer.new('code')
119
+ buffer.source = code
120
+ begin
121
+ Capataz::Rewriter.new(options).rewrite(buffer, Parser::CurrentRuby.new.parse(buffer))
122
+ rescue Exception => ex
123
+ if (logs = options[:logs]).is_a?(Hash) &&
124
+ (errors = (logs[:errors] ||= [])).is_a?(Array)
125
+ errors << "syntax error: #{ex.message}"
126
+ else
127
+ raise ex
128
+ end
129
+ end
130
+ end
131
+
132
+ def handle(obj, options = {})
133
+ if obj.capataz_proxy? || [NilClass, Fixnum, Symbol, String, TrueClass, FalseClass].any? { |type| obj.is_a?(type) }
134
+ obj
135
+ elsif obj.is_a?(Hash)
136
+ Capataz::HashProxy.new(obj)
137
+ else
138
+ Capataz::Proxy.new(obj, options)
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def allow_method_overrides
145
+ true #TODO Setup on config
146
+ end
147
+
148
+ def allowed_method?(options, instance, method)
149
+ if (allow = options[:allow])
150
+ if allow.is_a?(Proc)
151
+ return false unless allow.call(instance, method)
152
+ else
153
+ return false unless allow.include?(method)
154
+ end
155
+ end
156
+ if (deny = options[:deny])
157
+ if deny.is_a?(Proc)
158
+ return false if deny.call(instance, method)
159
+ else
160
+ return false if deny.include?(method)
161
+ end
162
+ end
163
+ true
164
+ end
165
+
166
+ def symbol_array_store(key, symbols)
167
+ set = @config[key]
168
+ symbols = [symbols] unless symbols.is_a?(Enumerable)
169
+ symbols.each { |symbol| set << (symbol.is_a?(Symbol) ? symbol : symbol.to_s.to_sym) }
170
+ end
171
+
172
+ def instances_store(key, objs, methods)
173
+ methods = [methods] unless methods.is_a?(Enumerable)
174
+ methods = methods.to_a.collect { |method| method.is_a?(Symbol) ? method : method.to_s.to_sym }
175
+ objs = [objs] unless objs.is_a?(Enumerable)
176
+ instances = @config[:instances]
177
+ objs.each do |obj|
178
+ (instances[obj] ||= {}).merge!(key => methods)
179
+ end
180
+ end
181
+
182
+ def store_options(entry_key, access_key, objs, options)
183
+ if options.is_a?(Enumerable)
184
+ options = options.flatten if options.is_a?(Array)
185
+ else
186
+ options = [options]
187
+ end
188
+ options =
189
+ if options.length == 1 && options[0].is_a?(Proc)
190
+ options[0]
191
+ else
192
+ options.collect { |option| option.is_a?(Symbol) ? option : option.to_s.to_sym }
193
+ end
194
+ objs = [objs] unless objs.is_a?(Enumerable)
195
+ entry = @config[entry_key]
196
+ objs.each do |obj|
197
+ if block_given?
198
+ fail "Illegal object #{obj}" unless yield(obj)
199
+ end
200
+ (entry[obj] ||= {}).merge!(access_key => options)
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ Capataz.config
207
+ end
@@ -0,0 +1,24 @@
1
+ class BasicObject
2
+ def capataz_proxy?
3
+ false
4
+ end
5
+
6
+ def capataz_slave
7
+ self
8
+ end
9
+ end
10
+
11
+ module Parser
12
+ module Source
13
+ class Range
14
+
15
+ def eql?(obj)
16
+ self == obj
17
+ end
18
+
19
+ def hash
20
+ begin_pos + 83 * end_pos
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,76 @@
1
+
2
+ module Capataz
3
+
4
+ class Proxy
5
+
6
+ instance_methods.each do |m|
7
+ if m !~ /^(__|instance_eval|object_id)/
8
+ class_eval("
9
+ def #{m}(*args, &block)
10
+ method_missing(:#{m}, *args, &block)
11
+ end")
12
+ end
13
+ end
14
+
15
+ def initialize(obj, options = {})
16
+ @obj = obj
17
+ if (@options = options || {})[:constant] && !Capataz.allowed_constant?(obj)
18
+ fail "Illegal access to constant #{obj}"
19
+ end
20
+ end
21
+
22
+ def method(sym)
23
+ if Capataz.instance_response_to?(@obj, symbol)
24
+ @obj.method(sym)
25
+ else
26
+ nil
27
+ end
28
+ end
29
+
30
+ def method_missing(symbol, *args, &block)
31
+ if Capataz.instance_response_to?(@obj, symbol)
32
+ @obj.send(symbol, *args, &block)
33
+ else
34
+ fail NoMethodError, "undefined method #{symbol} for #{@obj}"
35
+ end
36
+ end
37
+
38
+ def is_a?(type)
39
+ if type.capataz_proxy?
40
+ @obj.is_a?(type.capataz_slave)
41
+ else
42
+ @obj.is_a?(type)
43
+ end
44
+ end
45
+
46
+ def capataz_proxy?
47
+ true
48
+ end
49
+
50
+ def capataz_slave
51
+ @obj
52
+ end
53
+
54
+ def class
55
+ @obj.class
56
+ end
57
+
58
+ def respond_to?(*args)
59
+ Capataz.instance_response_to?(@obj, *args)
60
+ end
61
+ end
62
+
63
+ class HashProxy < Proxy
64
+
65
+ def []=(key, value)
66
+ key = key.capataz_slave if key.capataz_proxy?
67
+ @obj[key] = value
68
+ end
69
+
70
+ def [](key)
71
+ key = key.capataz_slave if key.capataz_proxy?
72
+ value = @obj[key]
73
+ value.capataz_proxy? ? value.capataz_slave : value
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,165 @@
1
+ require 'capataz/source_rewriter'
2
+
3
+ module Capataz
4
+
5
+ class Rewriter < Parser::Rewriter
6
+
7
+ attr_reader :logs
8
+
9
+ def initialize(options = {})
10
+ @options = options || {}
11
+ @logs = options[:logs] || {}
12
+ @self_linker = options[:self_linker]
13
+ @self_send_prefixer = options[:self_send_prefixer]
14
+ @capatized_nodes = Set.new
15
+ end
16
+
17
+ def rewrite(source_buffer, ast)
18
+ @logs.clear
19
+ @capatized_nodes.clear
20
+ @source_rewriter = Capataz::SourceRewriter.new(source_buffer)
21
+
22
+ process(ast)
23
+
24
+ @source_rewriter.preprocess
25
+ @source_rewriter.process
26
+ end
27
+
28
+ def on_array(node)
29
+ super
30
+ node.children.each { |child| decapatize(child) }
31
+ end
32
+
33
+ def on_send(node)
34
+ super
35
+ unless Capataz.allows_invocation_of(method_name = node.children[1])
36
+ report_error("invoking method #{method_name} is not allowed")
37
+ end
38
+ if (left = node.children[0])
39
+ capatize(left)
40
+ elsif node.type == :send
41
+ unless @self_linker.link?(method_name)
42
+ report_error("error linking #{method_name}")
43
+ end if @self_linker
44
+ (@logs[:self_sends] ||= Set.new) << method_name
45
+ prefix = @self_send_prefixer ? @self_send_prefixer.prefix(method_name, @self_linker) : ''
46
+ insert_before(node.location.expression, "::Capataz.handle(self).#{prefix}")
47
+ end
48
+ i = 2
49
+ while i < node.children.length
50
+ decapatize(node.children[i])
51
+ i += 1
52
+ end
53
+ end
54
+
55
+ def on_return(node)
56
+ report_error('can not use return') unless Capataz.can_declare?(:return)
57
+ super
58
+ capatize(node.children[2])
59
+ end
60
+
61
+ def on_casgn(node)
62
+ report_error('can not define (or override) constants') unless Capataz.can_declare?(:constant)
63
+ super
64
+ capatize(node.children[2])
65
+ end
66
+
67
+ def on_lvasgn(node)
68
+ super
69
+ capatize(node.children[1])
70
+ end
71
+
72
+ def on_class(node)
73
+ report_error('can not define classes') unless Capataz.can_declare?(:class)
74
+ super
75
+ end
76
+
77
+ def on_module(node)
78
+ report_error('can not define modules') unless Capataz.can_declare?(:module)
79
+ super
80
+ end
81
+
82
+ def on_def(node)
83
+ report_error('can not define methods') unless Capataz.can_declare?(:def)
84
+ super
85
+ insert_before(node.location.expression, ";::Capataz.denied_override_of(self, :#{node.children[0]});") unless Capataz.allow_method_overrides
86
+ end
87
+
88
+ def on_self(_)
89
+ report_error('can not access to self') unless Capataz.can_declare?(:self)
90
+ end
91
+
92
+ def on_yield(node)
93
+ report_error('can not make yield calls') unless Capataz.can_declare?(:yield)
94
+ super
95
+ end
96
+
97
+ def on_ivasgn(_)
98
+ report_error('can not access instance variables') unless Capataz.can_declare?(:ivar)
99
+ super
100
+ end
101
+
102
+ def on_ivar(_)
103
+ report_error('can not access instance variables') unless Capataz.can_declare?(:ivar)
104
+ super
105
+ end
106
+
107
+ def on_cvasgn(_)
108
+ report_error('can not access class variables') unless Capataz.can_declare?(:cvar)
109
+ super
110
+ end
111
+
112
+ def on_cvar(_)
113
+ report_error('can not access class variables') unless Capataz.can_declare?(:cvar)
114
+ super
115
+ end
116
+
117
+ def on_gvar(_)
118
+ report_error('can not access global variables') unless Capataz.can_declare?(:gvar)
119
+ super
120
+ end
121
+
122
+ def on_gvasgn(_)
123
+ report_error('can not access global variables') unless Capataz.can_declare?(:gvar)
124
+ super
125
+ end
126
+
127
+ private
128
+
129
+ def report_error(message)
130
+ if @options[:halt_on_error]
131
+ fail message
132
+ else
133
+ (logs[:errors] ||= []) << message
134
+ end
135
+ end
136
+
137
+ def capatize(node, options = {})
138
+ if node && !@capatized_nodes.include?(node)
139
+ @capatized_nodes << node
140
+ options[:constant] = true if node.type == :const
141
+ @source_rewriter.insert_before_multi(node.location.expression, '::Capataz.handle(')
142
+ if !options.empty?
143
+ @source_rewriter.insert_after_multi(node.location.expression, ", #{options.to_a.collect { |item| "#{item[0]}: #{item[1]}" }.join(',')})")
144
+ else
145
+ @source_rewriter.insert_after_multi(node.location.expression, ')')
146
+ end
147
+ end
148
+ end
149
+
150
+ def decapatize(node)
151
+ unless node.type == :hash
152
+ @source_rewriter.insert_before_multi(node.location.expression, '(')
153
+ @source_rewriter.insert_after_multi(node.location.expression, ').capataz_slave')
154
+ end
155
+ end
156
+
157
+ def const_from(node)
158
+ if node
159
+ const_from(node.children[0]) + '::' + node.children[1].to_s
160
+ else
161
+ ''
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Capataz
3
+
4
+ class SourceRewriter < Parser::Source::Rewriter
5
+
6
+ def preprocess
7
+ hash = {}
8
+ @queue.each do |action|
9
+ if a = hash[action.range]
10
+ hash[action.range] = Parser::Source::Rewriter::Action.new(a.range, action.replacement + a.replacement)
11
+ else
12
+ hash[action.range] = action
13
+ end
14
+ end
15
+ @queue = hash.values.to_a
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Capataz
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capataz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Maikel Arcia
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: parser
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - macarci@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - CODE_OF_CONDUCT.md
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - bin/console
68
+ - bin/setup
69
+ - capataz.gemspec
70
+ - lib/capataz.rb
71
+ - lib/capataz/core_ext.rb
72
+ - lib/capataz/proxy.rb
73
+ - lib/capataz/rewriter.rb
74
+ - lib/capataz/source_rewriter.rb
75
+ - lib/capataz/version.rb
76
+ homepage: https://github.com/macarci/capataz
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.4.6
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Provides Ruby code execution control by defining rules for syntax and runtime
100
+ behavior.
101
+ test_files: []