opt_parse_validator 0.0.2

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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +4 -0
  5. data/.simplecov +4 -0
  6. data/.travis.yml +15 -0
  7. data/Gemfile +6 -0
  8. data/README.md +40 -0
  9. data/Rakefile +9 -0
  10. data/lib/opt_parse_validator/hacks.rb +15 -0
  11. data/lib/opt_parse_validator/options_file.rb +62 -0
  12. data/lib/opt_parse_validator/opts/base.rb +74 -0
  13. data/lib/opt_parse_validator/opts/boolean.rb +20 -0
  14. data/lib/opt_parse_validator/opts/choice.rb +33 -0
  15. data/lib/opt_parse_validator/opts/credentials.rb +14 -0
  16. data/lib/opt_parse_validator/opts/directory_path.rb +10 -0
  17. data/lib/opt_parse_validator/opts/file_path.rb +24 -0
  18. data/lib/opt_parse_validator/opts/integer.rb +12 -0
  19. data/lib/opt_parse_validator/opts/path.rb +61 -0
  20. data/lib/opt_parse_validator/opts/positive_integer.rb +13 -0
  21. data/lib/opt_parse_validator/opts/proxy.rb +5 -0
  22. data/lib/opt_parse_validator/opts/string.rb +6 -0
  23. data/lib/opt_parse_validator/opts/uri.rb +24 -0
  24. data/lib/opt_parse_validator/opts/url.rb +9 -0
  25. data/lib/opt_parse_validator/opts.rb +3 -0
  26. data/lib/opt_parse_validator/version.rb +4 -0
  27. data/lib/opt_parse_validator.rb +77 -0
  28. data/opt_parse_validator.gemspec +32 -0
  29. data/spec/fixtures/options_file/default.json +4 -0
  30. data/spec/fixtures/options_file/malformed.json +4 -0
  31. data/spec/fixtures/options_file/override.yml +1 -0
  32. data/spec/fixtures/options_file/unsupported.ext +1 -0
  33. data/spec/fixtures/r.txt +1 -0
  34. data/spec/fixtures/rwx.txt +1 -0
  35. data/spec/lib/opt_parse_validator/options_file_spec.rb +50 -0
  36. data/spec/lib/opt_parse_validator/opts/base_spec.rb +169 -0
  37. data/spec/lib/opt_parse_validator/opts/boolean_spec.rb +36 -0
  38. data/spec/lib/opt_parse_validator/opts/choice_spec.rb +78 -0
  39. data/spec/lib/opt_parse_validator/opts/credentials_spec.rb +23 -0
  40. data/spec/lib/opt_parse_validator/opts/direcyory_path_spec.rb +25 -0
  41. data/spec/lib/opt_parse_validator/opts/file_path_spec.rb +93 -0
  42. data/spec/lib/opt_parse_validator/opts/integer_spec.rb +19 -0
  43. data/spec/lib/opt_parse_validator/opts/path_spec.rb +7 -0
  44. data/spec/lib/opt_parse_validator/opts/positive_integer_spec.rb +19 -0
  45. data/spec/lib/opt_parse_validator/opts/proxy_spec.rb +12 -0
  46. data/spec/lib/opt_parse_validator/opts/uri_spec.rb +58 -0
  47. data/spec/lib/opt_parse_validator/opts/url_spec.rb +28 -0
  48. data/spec/lib/opt_parse_validator/version_spec.rb +7 -0
  49. data/spec/lib/opt_parse_validator_spec.rb +152 -0
  50. data/spec/spec_helper.rb +25 -0
  51. metadata +213 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b0a34c11c84d6fa32580ed925dac42346cee747
4
+ data.tar.gz: 7c50ea36943042d5cf7f8b77c15fd93b0969339c
5
+ SHA512:
6
+ metadata.gz: 051c726116d357bd876f87d9a113ba3c00f53a2b146e92e69d2447bef77de471fe2150f2c834356d52a1ec0b5b14f0b8e94e3177e3e6c84190ceac2068be1579
7
+ data.tar.gz: 910103742d3c7cfab15980043a02a169a9708f4ed3f11086ee280eec9d8cdd57621d82a8cf04f7739083f7384fd50c98e45ac2e5a129175c5a5461f52d2c8ff6
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ coverage
2
+ Gemfile.lock
3
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --fail-fast
data/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ LineLength:
2
+ Enabled: false
3
+ MethodLength:
4
+ Max: 20
data/.simplecov ADDED
@@ -0,0 +1,4 @@
1
+ SimpleCov.start do
2
+ add_filter '/spec/'
3
+ add_filter '_helper.rb'
4
+ end
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1.0
5
+ - 2.1.1
6
+ - 2.1.2
7
+ - ruby-head
8
+ matrix:
9
+ allow_failures:
10
+ - rvm: ruby-head
11
+ before_script:
12
+ - chmod 0400 spec/fixtures/r.txt
13
+ script:
14
+ - bundle exec rspec
15
+ - bundle exec rubocop
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ group :test do
5
+ gem 'coveralls', require: false
6
+ end
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ OptParseValidator
2
+ =================
3
+
4
+ [![Build Status](https://img.shields.io/travis/wpscanteam/OptParseValidator.svg)](https://travis-ci.org/wpscanteam/OptParseValidator)
5
+ [![Coverage Status](https://img.shields.io/coveralls/wpscanteam/OptParseValidator.svg)](https://coveralls.io/r/wpscanteam/OptParseValidator?branch=master)
6
+ [![Code Climate](https://img.shields.io/codeclimate/github/wpscanteam/OptParseValidator.svg)](https://codeclimate.com/github/wpscanteam/OptParseValidator)
7
+ [![Dependency Status](https://img.shields.io/gemnasium/wpscanteam/OptParseValidator.svg)](https://gemnasium.com/wpscanteam/OptParseValidator)
8
+
9
+
10
+ ### Available Validators & associated attributes:
11
+ - Boolean
12
+ - Choice
13
+ - :choices (mandatory)
14
+ - :case_sensitive
15
+ - Credentials
16
+ - Directory Path
17
+ - :exists
18
+ - :executable
19
+ - :readable
20
+ - :writable
21
+ - File Path
22
+ - :exists
23
+ - :executable
24
+ - :readable
25
+ - :writable
26
+ - Integer
27
+ - Positive Integer
28
+ - Path
29
+ - :file
30
+ - :directory
31
+ - :exists
32
+ - :executable
33
+ - :readable
34
+ - :writable
35
+ - Proxy
36
+ - :protocols
37
+ - String
38
+ - URI
39
+ - :protocols
40
+ - URL
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RuboCop::RakeTask.new
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ # Run rubocop & rspec before the build
9
+ task build: [:rubocop, :spec]
@@ -0,0 +1,15 @@
1
+ class OptionParser
2
+ # Hack to suppress the completion (expect for the -h/--help) which was leading to
3
+ # unwanted behaviours
4
+ # See https://github.com/wpscanteam/CMSScanner/issues/2
5
+ module Completion
6
+ class << self
7
+ alias_method :original_candidate, :candidate
8
+
9
+ def candidate(key, icase = false, pat = nil, &block)
10
+ # Maybe also do this for -v/--version ?
11
+ key == 'h' ? original_candidate('help', icase, pat, &block) : []
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,62 @@
1
+ require 'json'
2
+ require 'yaml'
3
+
4
+ module OptParseValidator
5
+ # TODO
6
+ class OptParser < OptionParser
7
+ def options_files
8
+ @options_files ||= []
9
+ end
10
+
11
+ def load_options_files
12
+ files_data = {}
13
+
14
+ options_files.each do |file|
15
+ data = parse_file(file)
16
+ files_data.merge!(data) if data
17
+ end
18
+
19
+ @opts.each do |opt|
20
+ # Annoying thing: the hash returned from parse_file is a string-full {"key"=>"value"}
21
+ # and not a ruby hash {key: value} :/ As a result, symbol.to_s has to be used
22
+ next unless files_data.key?(opt.to_sym.to_s)
23
+
24
+ @results[opt.to_sym] = opt.normalize(opt.validate(files_data[opt.to_sym.to_s]))
25
+ end
26
+ end
27
+
28
+ protected
29
+
30
+ # @param [ String ] file_path
31
+ #
32
+ # @return [ Hash ]
33
+ def parse_file(file_path)
34
+ return unless File.exist?(file_path)
35
+
36
+ file_ext = File.extname(file_path).delete('.')
37
+ method_to_call = "parse_#{file_ext}"
38
+
39
+ fail "The format #{file_ext} is not supported" unless respond_to?(method_to_call, true) # The true allows to check protected & private methods
40
+
41
+ begin
42
+ method(method_to_call).call(file_path)
43
+ rescue
44
+ raise "Parse Error, #{file_path} seems to be malformed"
45
+ end
46
+ end
47
+
48
+ # @param [ String ] file_path
49
+ #
50
+ # @return [ Hash ]
51
+ def parse_json(file_path)
52
+ JSON.parse(File.read(file_path))
53
+ end
54
+
55
+ # @param [ String ] file_path
56
+ #
57
+ # @return [ Hash ]
58
+ def parse_yml(file_path)
59
+ YAML.load_file(file_path)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,74 @@
1
+ module OptParseValidator
2
+ # Base Option
3
+ # This Option should not be called, children should be used.
4
+ class OptBase
5
+ attr_writer :required
6
+ attr_reader :option, :attrs
7
+
8
+ # @param [ Array ] option See OptionParser#on
9
+ # @param [ Hash ] attrs
10
+ # @option attrs [ Boolean ] :required
11
+ # @option attrs [ Mixed ] :default The default value to use if the option is not supplied
12
+ # @option attrs [ Boolean ] :to_sym If true, returns the symbol of the validated value
13
+ # @option attrs [ Array<Symbol> ] :normalize See #normalize
14
+ #
15
+ # @note The :default and :normalize 'logics' are done in OptParseValidator::OptParser#add_option
16
+ def initialize(option, attrs = {})
17
+ @option = option
18
+ @attrs = attrs
19
+ end
20
+
21
+ # @return [ Boolean ]
22
+ def required?
23
+ @required || attrs[:required]
24
+ end
25
+
26
+ # @param [ String ] value
27
+ def validate(value)
28
+ fail 'Empty option value supplied' if value.nil? || value.to_s.empty?
29
+ value
30
+ end
31
+
32
+ # Apply each methods from attrs[:normalize] to the value if possible
33
+ # User input should not be used in this attrs[:normalize]
34
+ #
35
+ # e.g: normalize: :to_sym will return the symbol of the value
36
+ # normalize: [:to_sym, :upcase] Will return the upercased symbol
37
+ #
38
+ # @param [ Mixed ] value
39
+ #
40
+ # @return [ Mixed ]
41
+ def normalize(value)
42
+ [*attrs[:normalize]].each do |method|
43
+ next unless method.is_a?(Symbol)
44
+
45
+ value = value.send(method) if value.respond_to?(method)
46
+ end
47
+
48
+ value
49
+ end
50
+
51
+ # @return [ Symbol ]
52
+ def to_sym
53
+ unless @symbol
54
+ long_option = to_long
55
+
56
+ fail "Could not find option symbol for #{option}" unless long_option
57
+
58
+ @symbol = long_option.gsub(/^--/, '').gsub(/-/, '_').to_sym
59
+ end
60
+ @symbol
61
+ end
62
+
63
+ # @return [ String ] The raw long option (e.g: --proxy)
64
+ def to_long
65
+ option.each do |option_attr|
66
+ if option_attr =~ /^--/
67
+ return option_attr.gsub(/ .*$/, '')
68
+ .gsub(/\[[^\]]+\]/, '')
69
+ end
70
+ end
71
+ nil
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,20 @@
1
+ module OptParseValidator
2
+ # Implementation of the Boolean Option
3
+ class OptBoolean < OptBase
4
+ TRUE_PATTERN = /\A(true|t|yes|y|1)\z/i
5
+ FALSE_PATTERN = /\A(false|f|no|n|0)\z/i
6
+
7
+ # @return [ Boolean ]
8
+ def validate(value)
9
+ value = value.to_s
10
+
11
+ if value.match(TRUE_PATTERN)
12
+ return true
13
+ elsif value.match(FALSE_PATTERN)
14
+ return false
15
+ else
16
+ fail 'Invalid boolean value, expected true|t|yes|y|1|false|f|no|n|0'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ module OptParseValidator
2
+ # Implementation of the Choice Option
3
+ class OptChoice < OptBase
4
+ # @param [ Array ] option See OptBase#new
5
+ # @param [ Hash ] attrs
6
+ # :choices [ Array ] The available choices (mandatory)
7
+ # :case_sensitive [ Boolean ] Default: false
8
+ def initialize(option, attrs = {})
9
+ fail 'The :choices attribute is mandatory' unless attrs.key?(:choices)
10
+ fail 'The :choices attribute must be an array' unless attrs[:choices].is_a?(Array)
11
+
12
+ super(option, attrs)
13
+ end
14
+
15
+ # @return [ String ]
16
+ # If :case_sensitive if false (or nil), the downcased value of the choice
17
+ # will be returned
18
+ def validate(value)
19
+ value = value.to_s
20
+ choices = attrs[:choices]
21
+
22
+ unless attrs[:case_sensitive]
23
+ value.downcase!
24
+ choices.map!(&:downcase)
25
+ end
26
+
27
+ fail "'#{value}' is not a valid choice, expected one " \
28
+ "of the followings: #{choices.join(',')}" unless choices.include?(value)
29
+
30
+ value
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module OptParseValidator
2
+ # Implementation of the Credentials Option
3
+ class OptCredentials < OptBase
4
+ # @return [ Hash ] A hash containing the :username and :password
5
+ def validate(value)
6
+ unless value.index(':')
7
+ fail 'Incorrect credentials format, username:password expected'
8
+ end
9
+ creds = value.split(':', 2)
10
+
11
+ { username: creds[0], password: creds[1] }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module OptParseValidator
2
+ # Implemetantion of the DirectoryPath Option
3
+ class OptDirectoryPath < OptPath
4
+ def initialize(option, attrs = {})
5
+ super(option, attrs)
6
+
7
+ @attrs.merge!(directory: true)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ module OptParseValidator
2
+ # Implementation of the FilePath Option
3
+ class OptFilePath < OptPath
4
+ # @param [ Array ] option See OptBase#new
5
+ # @param [ Hash ] attrs See OptPath#new
6
+ # :extensions [ Array | String ] The allowed extension(s)
7
+ def initialize(option, attrs = {})
8
+ super(option, attrs)
9
+
10
+ @attrs.merge!(file: true)
11
+ end
12
+
13
+ def allowed_attrs
14
+ # :extensions is put at the first place
15
+ [:extensions] + super
16
+ end
17
+
18
+ def check_extensions(path)
19
+ return if [*attrs[:extensions]].include?(path.extname.delete('.'))
20
+
21
+ fail "The extension of '#{path}' is not allowed"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ module OptParseValidator
2
+ # Implementation of the Integer Option
3
+ class OptInteger < OptBase
4
+ # @param [ String ] value
5
+ #
6
+ # @return [ Integer ]
7
+ def validate(value)
8
+ fail "#{value} is not an integer" if value.to_i.to_s != value
9
+ value.to_i
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ module OptParseValidator
2
+ # Implementation of the Path Option
3
+ class OptPath < OptBase
4
+ # Initialize attrs:
5
+ #
6
+ # :exists if set to false, will ignore the file? and directory? checks
7
+ #
8
+ # :file Check if the path is a file
9
+ # :directory Check if the path is a directory
10
+ #
11
+ # :executable
12
+ # :readable
13
+ # :writable
14
+ #
15
+
16
+ # @param [ String ] value
17
+ #
18
+ # @return [ String ]
19
+ def validate(value)
20
+ path = Pathname.new(value)
21
+ allowed_attrs.each do |key|
22
+ method = "check_#{key}"
23
+ send(method, path) if self.respond_to?(method) && attrs[key]
24
+ end
25
+
26
+ path.to_s
27
+ end
28
+
29
+ def allowed_attrs
30
+ [:file, :directory, :executable, :readable, :writable]
31
+ end
32
+
33
+ # @param [ Pathname ] path
34
+ def check_file(path)
35
+ fail "'#{path}' is not a file" unless path.file? || attrs[:exists] == false
36
+ end
37
+
38
+ # @param [ Pathname ] path
39
+ def check_directory(path)
40
+ fail "'#{path}' is not a directory" unless path.directory? || attrs[:exists] == false
41
+ end
42
+
43
+ # @param [ Pathname ] path
44
+ def check_executable(path)
45
+ fail "'#{path}' is not executable" unless path.executable?
46
+ end
47
+
48
+ # @param [ Pathname ] path
49
+ def check_readable(path)
50
+ fail "'#{path}' is not readable" unless path.readable?
51
+ end
52
+
53
+ # If the path does not exist, it will check for the parent
54
+ # directory write permission
55
+ #
56
+ # @param [ Pathname ] path
57
+ def check_writable(path)
58
+ fail "'#{path}' is not writable" if path.exist? && !path.writable? || !path.parent.writable?
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,13 @@
1
+ module OptParseValidator
2
+ # Implementation of the Positive Integer Option
3
+ class OptPositiveInteger < OptInteger
4
+ # @param [ String ] value
5
+ #
6
+ # @return [ Integer ]
7
+ def validate(value)
8
+ i = super(value)
9
+ fail "#{i} is not > 0" unless i > 0
10
+ i
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module OptParseValidator
2
+ # Implementation of the Proxy Option
3
+ class OptProxy < OptURI
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ module OptParseValidator
2
+ # Alias of OptBase
3
+ # Used for convenience
4
+ class OptString < OptBase
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ module OptParseValidator
2
+ # Implementation of the URI Option
3
+ class OptURI < OptBase
4
+ def allowed_protocols
5
+ @allowed_protocols ||= [*attrs[:protocols]]
6
+ end
7
+
8
+ # @param [ String ] value
9
+ #
10
+ # @return [ String ]
11
+ def validate(value)
12
+ uri = Addressable::URI.parse(value)
13
+ protocols = allowed_protocols
14
+
15
+ unless protocols.empty? || protocols.include?(uri.scheme)
16
+ # For future refs: will have to check if the uri.scheme exists,
17
+ # otherwise it means that the value was empty
18
+ fail Addressable::URI::InvalidURIError
19
+ end
20
+
21
+ uri.to_s
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module OptParseValidator
2
+ # Implementation of the URL Option
3
+ class OptURL < OptURI
4
+ # @return [ Array ] The allowed protocols
5
+ def allowed_protocols
6
+ %w(http https)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ %w(base string integer positive_integer choice boolean uri url proxy credentials path file_path directory_path).each do |opt|
2
+ require 'opt_parse_validator/opts/' + opt
3
+ end
@@ -0,0 +1,4 @@
1
+ # Gem Version
2
+ module OptParseValidator
3
+ VERSION = '0.0.2'
4
+ end
@@ -0,0 +1,77 @@
1
+ # Gems
2
+ require 'addressable/uri'
3
+ # Standard Libs
4
+ require 'optparse'
5
+ require 'pathname'
6
+ # Custom Libs
7
+ require 'opt_parse_validator/hacks'
8
+ require 'opt_parse_validator/opts'
9
+ require 'opt_parse_validator/version'
10
+ require 'opt_parse_validator/options_file'
11
+
12
+ # Gem namespace
13
+ module OptParseValidator
14
+ # Validator
15
+ class OptParser < OptionParser
16
+ attr_reader :symbols_used, :opts
17
+
18
+ def initialize(banner = nil, width = 32, indent = ' ' * 4)
19
+ @results = {}
20
+ @symbols_used = []
21
+ @opts = []
22
+
23
+ super(banner, width, indent)
24
+ end
25
+
26
+ # @param [ OptBase ] options
27
+ #
28
+ # @return [ void ]
29
+ def add(*options)
30
+ options.each { |option| add_option(option) }
31
+ end
32
+
33
+ # @param [ OptBase ] opt
34
+ #
35
+ # @return [ void ]
36
+ def add_option(opt)
37
+ fail "The option is not an OptBase, #{opt.class} supplied" unless opt.is_a?(OptBase)
38
+ fail "The option #{opt.to_sym} is already used !" if @symbols_used.include?(opt.to_sym)
39
+
40
+ @opts << opt
41
+ @symbols_used << opt.to_sym
42
+ # Set the default option value if it exists
43
+ @results[opt.to_sym] = opt.attrs[:default] if opt.attrs.key?(:default)
44
+
45
+ on(*opt.option) do |arg|
46
+ begin
47
+ @results[opt.to_sym] = opt.normalize(opt.validate(arg))
48
+ rescue => e
49
+ # Adds the long option name to the message
50
+ # e.g --proxy Invalid Scheme format.
51
+ raise e.class, "#{opt.to_long} #{e}"
52
+ end
53
+ end
54
+ end
55
+
56
+ # @return [ Hash ]
57
+ def results(argv = default_argv)
58
+ load_options_files
59
+ self.parse!(argv)
60
+ post_processing
61
+
62
+ @results
63
+ end
64
+
65
+ # Ensure that all required options are supplied
66
+ # Should be overriden to modify the behavior
67
+ #
68
+ # @return [ Void ]
69
+ def post_processing
70
+ @opts.each do |opt|
71
+ next unless opt.required? && !@results.key?(opt.to_sym)
72
+
73
+ fail "The option #{opt.to_sym} is required"
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'opt_parse_validator/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'opt_parse_validator'
9
+ s.version = OptParseValidator::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.required_ruby_version = '>= 2.0.0'
12
+ s.authors = ['WPScanTeam - Erwan le Rousseau']
13
+ s.email = ['erwan.lr@gmail.com']
14
+ s.summary = 'Testing Gem'
15
+ s.description = 'Testing Gem ...'
16
+ s.homepage = 'https://github.com/wpscanteam/OptParseValidator'
17
+ s.license = 'MIT'
18
+
19
+ s.files = `git ls-files -z`.split("\x0")
20
+ s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
21
+ s.test_files = s.files.grep(/^(test|spec|features)\//)
22
+ s.require_paths = ['lib']
23
+
24
+ s.add_dependency 'addressable', '~> 2.3'
25
+
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'rspec', '~> 3.1'
28
+ s.add_development_dependency 'rspec-its'
29
+ s.add_development_dependency 'bundler', '~> 1.6'
30
+ s.add_development_dependency 'rubocop', '~> 0.26'
31
+ s.add_development_dependency 'simplecov', '~> 0.9'
32
+ end
@@ -0,0 +1,4 @@
1
+ {
2
+ "verbose": true,
3
+ "override_me": "I should be overriden"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "verbose": true,
3
+ "":,
4
+ }
@@ -0,0 +1 @@
1
+ override_me: "Yeaa"
@@ -0,0 +1 @@
1
+ Unsupported file format
@@ -0,0 +1 @@
1
+ This file is a chmod 400
@@ -0,0 +1 @@
1
+ This file is a chmod 777