dpl-connect 1.8.43

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +36 -0
  6. data/Gemfile +100 -0
  7. data/LICENSE +22 -0
  8. data/README.md +934 -0
  9. data/Rakefile +1 -0
  10. data/TESTING.md +29 -0
  11. data/bin/dpl +5 -0
  12. data/dpl.gemspec +32 -0
  13. data/lib/dpl/cli.rb +66 -0
  14. data/lib/dpl/error.rb +3 -0
  15. data/lib/dpl/provider.rb +264 -0
  16. data/lib/dpl/provider/anynines.rb +13 -0
  17. data/lib/dpl/provider/appfog.rb +21 -0
  18. data/lib/dpl/provider/atlas.rb +108 -0
  19. data/lib/dpl/provider/azure_webapps.rb +48 -0
  20. data/lib/dpl/provider/bintray.rb +509 -0
  21. data/lib/dpl/provider/bitballoon.rb +22 -0
  22. data/lib/dpl/provider/bluemix_cloud_foundry.rb +23 -0
  23. data/lib/dpl/provider/boxfuse.rb +57 -0
  24. data/lib/dpl/provider/catalyze.rb +49 -0
  25. data/lib/dpl/provider/chef_supermarket.rb +85 -0
  26. data/lib/dpl/provider/cloud66.rb +38 -0
  27. data/lib/dpl/provider/cloud_files.rb +38 -0
  28. data/lib/dpl/provider/cloud_foundry.rb +43 -0
  29. data/lib/dpl/provider/code_deploy.rb +123 -0
  30. data/lib/dpl/provider/deis.rb +119 -0
  31. data/lib/dpl/provider/divshot.rb +23 -0
  32. data/lib/dpl/provider/elastic_beanstalk.rb +195 -0
  33. data/lib/dpl/provider/engine_yard.rb +90 -0
  34. data/lib/dpl/provider/firebase.rb +27 -0
  35. data/lib/dpl/provider/gae.rb +97 -0
  36. data/lib/dpl/provider/gcs.rb +59 -0
  37. data/lib/dpl/provider/hackage.rb +29 -0
  38. data/lib/dpl/provider/heroku.rb +18 -0
  39. data/lib/dpl/provider/heroku/api.rb +98 -0
  40. data/lib/dpl/provider/heroku/generic.rb +94 -0
  41. data/lib/dpl/provider/heroku/git.rb +28 -0
  42. data/lib/dpl/provider/lambda.rb +236 -0
  43. data/lib/dpl/provider/launchpad.rb +48 -0
  44. data/lib/dpl/provider/modulus.rb +23 -0
  45. data/lib/dpl/provider/npm.rb +64 -0
  46. data/lib/dpl/provider/openshift.rb +59 -0
  47. data/lib/dpl/provider/ops_works.rb +132 -0
  48. data/lib/dpl/provider/packagecloud.rb +144 -0
  49. data/lib/dpl/provider/pages.rb +79 -0
  50. data/lib/dpl/provider/puppet_forge.rb +43 -0
  51. data/lib/dpl/provider/pypi.rb +111 -0
  52. data/lib/dpl/provider/releases.rb +139 -0
  53. data/lib/dpl/provider/rubygems.rb +51 -0
  54. data/lib/dpl/provider/s3.rb +123 -0
  55. data/lib/dpl/provider/scalingo.rb +97 -0
  56. data/lib/dpl/provider/script.rb +29 -0
  57. data/lib/dpl/provider/surge.rb +33 -0
  58. data/lib/dpl/provider/testfairy.rb +190 -0
  59. data/lib/dpl/provider/transifex.rb +45 -0
  60. data/lib/dpl/version.rb +3 -0
  61. data/notes/engine_yard.md +1 -0
  62. data/notes/heroku.md +3 -0
  63. data/spec/cli_spec.rb +36 -0
  64. data/spec/provider/anynines_spec.rb +20 -0
  65. data/spec/provider/appfog_spec.rb +35 -0
  66. data/spec/provider/atlas_spec.rb +99 -0
  67. data/spec/provider/azure_webapps_spec.rb +95 -0
  68. data/spec/provider/bintray_spec.rb +259 -0
  69. data/spec/provider/bitballoon_spec.rb +32 -0
  70. data/spec/provider/bluemixcloudfoundry_spec.rb +23 -0
  71. data/spec/provider/boxfuse_spec.rb +16 -0
  72. data/spec/provider/catalyze_spec.rb +39 -0
  73. data/spec/provider/chef_supermarket_spec.rb +51 -0
  74. data/spec/provider/cloud66_spec.rb +44 -0
  75. data/spec/provider/cloud_files_spec.rb +88 -0
  76. data/spec/provider/cloudfoundry_spec.rb +71 -0
  77. data/spec/provider/code_deploy_spec.rb +360 -0
  78. data/spec/provider/deis_spec.rb +116 -0
  79. data/spec/provider/divshot_spec.rb +28 -0
  80. data/spec/provider/elastic_beanstalk_spec.rb +209 -0
  81. data/spec/provider/firebase_spec.rb +40 -0
  82. data/spec/provider/gae_spec.rb +26 -0
  83. data/spec/provider/gcs_spec.rb +115 -0
  84. data/spec/provider/hackage_spec.rb +47 -0
  85. data/spec/provider/heroku_spec.rb +357 -0
  86. data/spec/provider/lambda_spec.rb +432 -0
  87. data/spec/provider/launchpad_spec.rb +33 -0
  88. data/spec/provider/modulus_spec.rb +29 -0
  89. data/spec/provider/npm_spec.rb +95 -0
  90. data/spec/provider/openshift_spec.rb +91 -0
  91. data/spec/provider/ops_works_spec.rb +127 -0
  92. data/spec/provider/packagecloud_spec.rb +56 -0
  93. data/spec/provider/puppet_forge_spec.rb +60 -0
  94. data/spec/provider/pypi_spec.rb +103 -0
  95. data/spec/provider/releases_spec.rb +303 -0
  96. data/spec/provider/rubygems_spec.rb +106 -0
  97. data/spec/provider/s3_spec.rb +174 -0
  98. data/spec/provider/scalingo_spec.rb +64 -0
  99. data/spec/provider/script_spec.rb +26 -0
  100. data/spec/provider/surge_spec.rb +15 -0
  101. data/spec/provider/testfairy_spec.rb +86 -0
  102. data/spec/provider/transifex_spec.rb +110 -0
  103. data/spec/provider_spec.rb +210 -0
  104. data/spec/spec_helper.rb +20 -0
  105. metadata +279 -0
@@ -0,0 +1,79 @@
1
+ module DPL
2
+ class Provider
3
+ class Pages < Provider
4
+ """Implements Github Pages deployment
5
+
6
+ Options:
7
+ - repo [optional, for pushed to other repos]
8
+ - github-token [required]
9
+ - github-url [optional, defaults to github.com]
10
+ - target-branch [optional, defaults to gh-pages]
11
+ - local-dir [optional, defaults to `pwd`]
12
+ - fqdn [optional]
13
+ - project-name [optional, defaults to fqdn or repo slug]
14
+ - email [optional, defaults to deploy@travis-ci.org]
15
+ - name [optional, defaults to Deployment Bot]
16
+ """
17
+
18
+ require 'tmpdir'
19
+
20
+ experimental 'GitHub Pages'
21
+
22
+ def initialize(context, options)
23
+ super
24
+
25
+ @build_dir = options[:local_dir] || '.'
26
+ @project_name = options[:project_name] || fqdn || slug
27
+ @target_branch = options[:target_branch] || 'gh-pages'
28
+
29
+ @gh_fqdn = fqdn
30
+ @gh_url = options[:github_url] || 'github.com'
31
+ @gh_token = option(:github_token)
32
+
33
+ @gh_email = options[:email] || 'deploy@travis-ci.org'
34
+ @gh_name = "#{options[:name] || 'Deployment Bot'} (from Travis CI)"
35
+
36
+ @gh_ref = "#{@gh_url}/#{slug}.git"
37
+ end
38
+
39
+ def fqdn
40
+ options.fetch(:fqdn) { nil }
41
+ end
42
+
43
+ def slug
44
+ options.fetch(:repo) { context.env['TRAVIS_REPO_SLUG'] }
45
+ end
46
+
47
+ def check_auth
48
+ end
49
+
50
+ def needs_key?
51
+ false
52
+ end
53
+
54
+ def github_deploy
55
+ context.shell 'rm -rf .git > /dev/null 2>&1'
56
+ context.shell "touch \"deployed at `date` by #{@gh_name}\""
57
+ context.shell 'git init' or raise 'Could not create new git repo'
58
+ context.shell "git config user.email '#{@gh_email}'"
59
+ context.shell "git config user.name '#{@gh_name}'"
60
+ context.shell "echo '#{@gh_fqdn}' > CNAME" if @gh_fqdn
61
+ context.shell 'git add .'
62
+ context.shell "FILES=\"`git commit -m 'Deploy #{@project_name} to #{@gh_ref}:#{@target_branch}' | tail`\"; echo \"$FILES\"; echo \"$FILES\" | [ `wc -l` -lt 10 ] || echo '...'"
63
+ context.shell "git push --force --quiet 'https://#{@gh_token}@#{@gh_ref}' master:#{@target_branch} > /dev/null 2>&1"
64
+ end
65
+
66
+ def push_app
67
+ Dir.mktmpdir {|tmpdir|
68
+ FileUtils.cp_r("#{@build_dir}/.", tmpdir)
69
+ FileUtils.cd(tmpdir, :verbose => true) do
70
+ unless github_deploy
71
+ error "Couldn't push the build to #{@gh_ref}:#{@target_branch}"
72
+ end
73
+ end
74
+ }
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,43 @@
1
+ module DPL
2
+ class Provider
3
+ class PuppetForge < Provider
4
+ require 'pathname'
5
+
6
+ requires 'json_pure', :version => '< 2.0', :load => 'json/pure'
7
+ requires 'puppet', :load => 'puppet/face'
8
+ requires 'puppet-blacksmith', :load => 'puppet_blacksmith'
9
+
10
+ def modulefile
11
+ @modulefile ||= Blacksmith::Modulefile.new
12
+ end
13
+
14
+ def forge
15
+ @forge ||= Blacksmith::Forge.new(options[:user], options[:password], options[:url])
16
+ end
17
+
18
+ def build
19
+ pmod = Puppet::Face['module', :current]
20
+ pmod.build('./')
21
+ end
22
+
23
+ def needs_key?
24
+ false
25
+ end
26
+
27
+ def check_app
28
+ modulefile.metadata
29
+ end
30
+
31
+ def check_auth
32
+ raise Error, "must supply a user" unless option(:user)
33
+ raise Error, "must supply a password" unless option(:password)
34
+ end
35
+
36
+ def push_app
37
+ build
38
+ log "Uploading to Puppet Forge #{forge.username}/#{modulefile.name}"
39
+ forge.push!(modulefile.name)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,111 @@
1
+ module DPL
2
+ class Provider
3
+ class PyPI < Provider
4
+ DEFAULT_SERVER = 'https://upload.pypi.org/legacy/'
5
+ PYPIRC_FILE = '~/.pypirc'
6
+
7
+ def pypi_user
8
+ option(:username, :user) || context.env['PYPI_USER'] || context.env['PYPI_USERNAME']
9
+ end
10
+
11
+ def pypi_password
12
+ options[:password] || context.env['PYPI_PASSWORD']
13
+ end
14
+
15
+ def pypi_server
16
+ options[:server] || context.env['PYPI_SERVER'] || DEFAULT_SERVER
17
+ end
18
+
19
+ def pypi_distributions
20
+ options[:distributions] || context.env['PYPI_DISTRIBUTIONS'] || 'sdist'
21
+ end
22
+
23
+ def pypi_docs_dir_option
24
+ docs_dir = options[:docs_dir] || context.env['PYPI_DOCS_DIR'] || ''
25
+ if !docs_dir.empty?
26
+ '--upload-dir ' + docs_dir
27
+ end
28
+ end
29
+
30
+ def skip_upload_docs?
31
+ ! options.has_key?(:skip_upload_docs) ||
32
+ (options.has_key?(:skip_upload_docs) && options[:skip_upload_docs])
33
+ end
34
+
35
+ def self.install_setuptools
36
+ shell 'wget https://bootstrap.pypa.io/ez_setup.py -O - | sudo python'
37
+ shell 'rm -f setuptools-*.zip'
38
+ end
39
+
40
+ def self.install_twine
41
+ shell("pip install twine", retry: true) if `which twine`.chop.empty?
42
+ end
43
+
44
+ def initialize(*args)
45
+ super(*args)
46
+ self.class.pip 'wheel' if pypi_distributions.to_s.include? 'bdist_wheel'
47
+ end
48
+
49
+ install_setuptools
50
+ install_twine
51
+
52
+ def config
53
+ {
54
+ :header => '[distutils]',
55
+ :servers_line => 'index-servers = pypi',
56
+ :servers => {
57
+ 'pypi' => [
58
+ "repository: #{pypi_server}",
59
+ "username: #{pypi_user}",
60
+ "password: #{pypi_password}",
61
+ ]
62
+ }
63
+ }
64
+ end
65
+
66
+ def write_servers(f)
67
+ config[:servers].each do |key, val|
68
+ f.puts " " * 4 + key
69
+ end
70
+
71
+ config[:servers].each do |key, val|
72
+ f.puts "[#{key}]"
73
+ f.puts val
74
+ end
75
+ end
76
+
77
+ def write_config
78
+ File.open(File.expand_path(PYPIRC_FILE), 'w') do |f|
79
+ config.each do |key, val|
80
+ f.puts(val) if val.is_a? String or val.is_a? Array
81
+ end
82
+ write_servers(f)
83
+ end
84
+ end
85
+
86
+ def check_auth
87
+ error "missing PyPI username" unless pypi_user
88
+ error "missing PyPI password" unless pypi_password
89
+ write_config
90
+ log "Authenticated as #{pypi_user}"
91
+ end
92
+
93
+ def check_app
94
+ end
95
+
96
+ def needs_key?
97
+ false
98
+ end
99
+
100
+ def push_app
101
+ context.shell "python setup.py #{pypi_distributions}"
102
+ context.shell "twine upload -r pypi dist/*"
103
+ context.shell "rm -rf dist/*"
104
+ unless skip_upload_docs?
105
+ log "Uploading documentation (skip with \"skip_upload_docs: true\")"
106
+ context.shell "python setup.py upload_docs #{pypi_docs_dir_option} -r #{pypi_server}"
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,139 @@
1
+ module DPL
2
+ class Provider
3
+ class Releases < Provider
4
+ require 'pathname'
5
+
6
+ if RUBY_VERSION >= "2.0.0"
7
+ requires 'octokit', version: '~> 4.6.2'
8
+ else
9
+ requires 'octokit', version: '~> 4.3.0'
10
+ end
11
+
12
+ requires 'mime-types', version: '~> 2.0'
13
+
14
+ def travis_tag
15
+ # Check if $TRAVIS_TAG is unset or set but empty
16
+ if context.env.fetch('TRAVIS_TAG','') == ''
17
+ nil
18
+ else
19
+ context.env['TRAVIS_TAG']
20
+ end
21
+ end
22
+
23
+ def get_tag
24
+ if travis_tag.nil?
25
+ @tag ||= `git describe --tags --exact-match 2>/dev/null`.chomp
26
+ else
27
+ @tag ||= travis_tag
28
+ end
29
+ end
30
+
31
+ def api
32
+ if options[:user] and options[:password]
33
+ @api ||= Octokit::Client.new(:login => options[:user], :password => options[:password])
34
+ else
35
+ @api ||= Octokit::Client.new(:access_token => option(:api_key))
36
+ end
37
+ end
38
+
39
+ def slug
40
+ options.fetch(:repo) { context.env['TRAVIS_REPO_SLUG'] }
41
+ end
42
+
43
+ def releases
44
+ @releases ||= api.releases(slug)
45
+ end
46
+
47
+ def user
48
+ @user ||= api.user
49
+ end
50
+
51
+ def files
52
+ if options[:file_glob]
53
+ Array(options[:file]).map do |glob|
54
+ Dir.glob(glob)
55
+ end.flatten
56
+ else
57
+ Array(options[:file])
58
+ end
59
+ end
60
+
61
+ def needs_key?
62
+ false
63
+ end
64
+
65
+ def check_app
66
+ log "Deploying to repo: #{slug}"
67
+
68
+ context.shell 'git fetch --tags' if travis_tag.nil?
69
+ log "Current tag is: #{get_tag}"
70
+ end
71
+
72
+ def setup_auth
73
+ user.login
74
+ end
75
+
76
+ def check_auth
77
+ setup_auth
78
+
79
+ unless api.scopes.include? 'public_repo' or api.scopes.include? 'repo'
80
+ raise Error, "Dpl does not have permission to upload assets. Make sure your token contains the repo or public_repo scope."
81
+ end
82
+
83
+ log "Logged in as #{user.name}"
84
+ end
85
+
86
+ def push_app
87
+ tag_matched = false
88
+ release_url = nil
89
+
90
+ if options[:release_number]
91
+ tag_matched = true
92
+ release_url = "https://api.github.com/repos/" + slug + "/releases/" + options[:release_number]
93
+ else
94
+ releases.each do |release|
95
+ if release.tag_name == get_tag
96
+ release_url = release.rels[:self].href
97
+ tag_matched = true
98
+ end
99
+ end
100
+ end
101
+
102
+ #If for some reason GitHub hasn't already created a release for the tag, create one
103
+ if tag_matched == false
104
+ release_url = api.create_release(slug, get_tag, options.merge({:draft => true})).rels[:self].href
105
+ end
106
+
107
+ files.each do |file|
108
+ existing_url = nil
109
+ filename = Pathname.new(file).basename.to_s
110
+ api.release(release_url).rels[:assets].get.data.each do |existing_file|
111
+ if existing_file.name == filename
112
+ existing_url = existing_file.url
113
+ end
114
+ end
115
+ if !existing_url
116
+ upload_file(file, filename, release_url)
117
+ elsif existing_url && options[:overwrite]
118
+ log "#{filename} already exists, overwriting."
119
+ api.delete_release_asset(existing_url)
120
+ upload_file(file, filename, release_url)
121
+ else
122
+ log "#{filename} already exists, skipping."
123
+ end
124
+ end
125
+
126
+ api.update_release(release_url, {:draft => false}.merge(options))
127
+ end
128
+
129
+ def upload_file(file, filename, release_url)
130
+ content_type = MIME::Types.type_for(file).first.to_s
131
+ if content_type.empty?
132
+ # Specify the default content type, as it is required by GitHub
133
+ content_type = "application/octet-stream"
134
+ end
135
+ api.upload_asset(release_url, file, {:name => filename, :content_type => content_type})
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,51 @@
1
+ module DPL
2
+ class Provider
3
+ class RubyGems < Provider
4
+ requires 'gems', version: '>= 0.8.3'
5
+
6
+ def setup_auth
7
+ ::Gems.key = option(:api_key) if options[:api_key]
8
+ ::Gems.username = option(:user) unless options[:api_key]
9
+ ::Gems.password = option(:password) unless options[:api_key]
10
+ end
11
+
12
+ def needs_key?
13
+ false
14
+ end
15
+
16
+ def setup_gem
17
+ options[:gem] ||= options[:app]
18
+ end
19
+
20
+ def gemspec
21
+ options[:gemspec].gsub('.gemspec', '') if options[:gemspec]
22
+ end
23
+
24
+ def check_app
25
+ setup_auth
26
+ setup_gem
27
+ log "Looking up gem #{options[:gem]}"
28
+ info = ::Gems.info(options[:gem])
29
+ log "Found gem #{info['name']}"
30
+ end
31
+
32
+ def check_auth
33
+ setup_auth
34
+ log "Authenticated with username #{::Gems.username}" if ::Gems.username
35
+ end
36
+
37
+ def push_app
38
+ setup_auth
39
+ setup_gem
40
+ context.shell "gem build #{gemspec || option(:gem)}.gemspec"
41
+ Dir.glob("#{gemspec || option(:gem)}-*.gem") do |f|
42
+ if options[:host]
43
+ log ::Gems.push(File.new(f), options[:host])
44
+ else
45
+ log ::Gems.push(File.new f)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,123 @@
1
+ require 'json'
2
+
3
+ module DPL
4
+ class Provider
5
+ class S3 < Provider
6
+ requires 'aws-sdk', version: '~> 2.0'
7
+ requires 'mime-types', version: '~> 2.0'
8
+
9
+ def api
10
+ @api ||= ::Aws::S3::Resource.new(s3_options)
11
+ end
12
+
13
+ def needs_key?
14
+ false
15
+ end
16
+
17
+ def check_app
18
+ log 'Warning: The endpoint option is no longer used and can be removed.' if options[:endpoint]
19
+ end
20
+
21
+ def access_key_id
22
+ options[:access_key_id] || context.env['AWS_ACCESS_KEY_ID'] || raise(Error, "missing access_key_id")
23
+ end
24
+
25
+ def secret_access_key
26
+ options[:secret_access_key] || context.env['AWS_SECRET_ACCESS_KEY'] || raise(Error, "missing secret_access_key")
27
+ end
28
+
29
+ def s3_options
30
+ {
31
+ region: options[:region] || 'us-east-1',
32
+ credentials: ::Aws::Credentials.new(access_key_id, secret_access_key)
33
+ }
34
+ end
35
+
36
+ def check_auth
37
+ log "Logging in with Access Key: #{access_key_id[-4..-1].rjust(20, '*')}"
38
+ end
39
+
40
+ def upload_path(filename)
41
+ [options[:upload_dir], filename].compact.join("/")
42
+ end
43
+
44
+ def push_app
45
+ glob_args = ["**/*"]
46
+ glob_args << File::FNM_DOTMATCH if options[:dot_match]
47
+ Dir.chdir(options.fetch(:local_dir, Dir.pwd)) do
48
+ Dir.glob(*glob_args) do |filename|
49
+ opts = content_data_for(filename)
50
+ opts[:cache_control] = get_option_value_by_filename(options[:cache_control], filename) if options[:cache_control]
51
+ opts[:acl] = options[:acl].gsub(/_/, '-') if options[:acl]
52
+ opts[:expires] = get_option_value_by_filename(options[:expires], filename) if options[:expires]
53
+ opts[:storage_class] = options[:storage_class] if options[:storage_class]
54
+ opts[:server_side_encryption] = "AES256" if options[:server_side_encryption]
55
+ unless File.directory?(filename)
56
+ log "uploading #{filename.inspect} with #{opts.inspect}"
57
+ result = api.bucket(option(:bucket)).object(upload_path(filename)).upload_file(filename, opts)
58
+ warn "error while uploading #{filename.inspect}" unless result
59
+ end
60
+ end
61
+ end
62
+
63
+ if suffix = options[:index_document_suffix]
64
+ api.bucket(option(:bucket)).website.put(
65
+ website_configuration: {
66
+ index_document: {
67
+ suffix: suffix
68
+ }
69
+ }
70
+ )
71
+ end
72
+ end
73
+
74
+ def deploy
75
+ super
76
+ rescue ::Aws::S3::Errors::InvalidAccessKeyId
77
+ raise Error, "Invalid S3 Access Key Id, Stopping Deploy"
78
+ rescue ::Aws::S3::Errors::ChecksumError
79
+ raise Error, "Aws Secret Key does not match Access Key Id, Stopping Deploy"
80
+ rescue ::Aws::S3::Errors::AccessDenied
81
+ raise Error, "Oops, It looks like you tried to write to a bucket that isn't yours or doesn't exist yet. Please create the bucket before trying to write to it."
82
+ end
83
+
84
+ private
85
+ def content_data_for(path)
86
+ content_data = {}
87
+ content_type = MIME::Types.type_for(path).first
88
+ content_data[:content_type] = content_type.to_s
89
+
90
+ encoding = encoding_for(path)
91
+ if detect_encoding?
92
+ content_data[:content_encoding] = encoding if encoding
93
+ end
94
+
95
+ if encoding == 'text' && default_text_charset?
96
+ content_data[:content_type] = "#{content_data[:content_type]}; charset=#{default_text_charset}"
97
+ end
98
+
99
+ return content_data
100
+ end
101
+
102
+ def get_option_value_by_filename(option_values, filename)
103
+ return option_values if !option_values.kind_of?(Array)
104
+ preferred_value = nil
105
+ hashes = option_values.select {|value| value.kind_of?(Hash) }
106
+ hashes.each do |hash|
107
+ hash.each do |value, patterns|
108
+ unless patterns.kind_of?(Array)
109
+ patterns = [patterns]
110
+ end
111
+ patterns.each do |pattern|
112
+ if File.fnmatch?(pattern, filename)
113
+ preferred_value = value
114
+ end
115
+ end
116
+ end
117
+ end
118
+ preferred_value = option_values.select {|value| value.kind_of?(String) }.last if preferred_value.nil?
119
+ return preferred_value
120
+ end
121
+ end
122
+ end
123
+ end