dotenv 2.0.0.beta → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 082cf9f284dde0511d6c31a21bd1b7f93b9804c3
4
- data.tar.gz: bcacb89f7cbf92eea2a2e12764db45a64c7909b1
3
+ metadata.gz: 9ccf9d3a79db7a52a63cb5aeca87cec81e21e3ec
4
+ data.tar.gz: abb6bc7fad7f6b2e2c300ff6b6141f30ccb0bc37
5
5
  SHA512:
6
- metadata.gz: 79fd1380227329afe5da7c1d2291e297106ba9f54cab22b204068e035f029bee4bec34289f424d70d3bfa92ce81f772b2632a4a5c1328b1ddd7e3e3938fcc290
7
- data.tar.gz: bb84a49f6a65088eec50233de800118fea98de0eb097c63b88ada013d474375b1565548570982254866e93ac836ec25df9bf3a1884d4f866cd7355862954eb1d
6
+ metadata.gz: d48b1e23d0ddfac1d8342f97fe4ae862aa43316617561a0d1f702663af6d9ee21716cdef113570a263301422a2e474a572b24992b9fba2114ca3615af6768ab6
7
+ data.tar.gz: b2c31269eb2977d37b0707759ad1e03ba428a7ed8a46927ec4b2fa2e23a3f8ba8302c5bc03d46a590f5489b413f24d506c2381b76e6c594364f2eb86199b27dd
data/README.md CHANGED
@@ -101,9 +101,19 @@ Whenever your application loads, these variables will be available in `ENV`:
101
101
  config.fog_directory = ENV['S3_BUCKET']
102
102
  ```
103
103
 
104
+ Comments may be added to your file as such:
105
+
106
+ ```shell
107
+ # This is a comment
108
+ SECRET_KEY=YOURSECRETKEYGOESHERE # comment
109
+ SECRET_HASH="something-with-a-#-hash"
110
+ ```
111
+
112
+ Variable names may not contain the `#` symbol. Values can use the `#` if they are enclosed in quotes.
113
+
104
114
  ## Multiple Rails Environments
105
115
 
106
- dotenv was originally created to load configuration variables into `ENV` in *development*. There are typically better ways to manage configuration in production environments environments—such as `/etc/environment` managed by [Puppet](https://github.com/puppetlabs/puppet) or [Chef](https://github.com/opscode/chef), `heroku config`, etc.
116
+ dotenv was originally created to load configuration variables into `ENV` in *development*. There are typically better ways to manage configuration in production environments - such as `/etc/environment` managed by [Puppet](https://github.com/puppetlabs/puppet) or [Chef](https://github.com/opscode/chef), `heroku config`, etc.
107
117
 
108
118
  However, some find dotenv to be a convenient way to configure Rails applications in staging and production environments, and you can do that by defining environment-specific files like `.env.production` or `.env.test`.
109
119
 
data/bin/dotenv CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'dotenv/cli'
3
+ require "dotenv/cli"
4
4
  Dotenv::CLI.new(ARGV).run
data/lib/dotenv.rb CHANGED
@@ -1,16 +1,19 @@
1
- require 'dotenv/parser'
2
- require 'dotenv/environment'
1
+ require "dotenv/parser"
2
+ require "dotenv/environment"
3
3
 
4
+ # The top level Dotenv module. The entrypoint for the application logic.
4
5
  module Dotenv
5
- extend self
6
+ class << self
7
+ attr_accessor :instrumenter
8
+ end
6
9
 
7
- attr_accessor :instrumenter
10
+ module_function
8
11
 
9
12
  def load(*filenames)
10
13
  with(*filenames) do |f|
11
- if File.exist?(f)
14
+ ignoring_nonexistent_files do
12
15
  env = Environment.new(f)
13
- instrument('dotenv.load', :env => env) { env.apply }
16
+ instrument("dotenv.load", :env => env) { env.apply }
14
17
  end
15
18
  end
16
19
  end
@@ -19,16 +22,16 @@ module Dotenv
19
22
  def load!(*filenames)
20
23
  with(*filenames) do |f|
21
24
  env = Environment.new(f)
22
- instrument('dotenv.load', :env => env) { env.apply }
25
+ instrument("dotenv.load", :env => env) { env.apply }
23
26
  end
24
27
  end
25
28
 
26
29
  # same as `load`, but will override existing values in `ENV`
27
30
  def overload(*filenames)
28
31
  with(*filenames) do |f|
29
- if File.exist?(f)
32
+ ignoring_nonexistent_files do
30
33
  env = Environment.new(f)
31
- instrument('dotenv.overload', :env => env) { env.apply! }
34
+ instrument("dotenv.overload", :env => env) { env.apply! }
32
35
  end
33
36
  end
34
37
  end
@@ -37,12 +40,10 @@ module Dotenv
37
40
  #
38
41
  # Returns a hash of all the loaded environment variables.
39
42
  def with(*filenames, &block)
40
- filenames << '.env' if filenames.empty?
43
+ filenames << ".env" if filenames.empty?
41
44
 
42
- {}.tap do |hash|
43
- filenames.each do |filename|
44
- hash.merge! block.call(File.expand_path(filename)) || {}
45
- end
45
+ filenames.reduce({}) do |hash, filename|
46
+ hash.merge! block.call(File.expand_path(filename)) || {}
46
47
  end
47
48
  end
48
49
 
@@ -53,4 +54,9 @@ module Dotenv
53
54
  block.call
54
55
  end
55
56
  end
57
+
58
+ def ignoring_nonexistent_files
59
+ yield
60
+ rescue Errno::ENOENT
61
+ end
56
62
  end
data/lib/dotenv/cli.rb CHANGED
@@ -1,6 +1,8 @@
1
- require 'dotenv'
1
+ require "dotenv"
2
2
 
3
3
  module Dotenv
4
+ # The CLI is a class responsible of handling all the command line interface
5
+ # logic.
4
6
  class CLI
5
7
  attr_reader :argv
6
8
 
@@ -9,23 +11,26 @@ module Dotenv
9
11
  end
10
12
 
11
13
  def run
12
- filenames = if pos = argv.index('-f')
13
- # drop the -f
14
- argv.delete_at pos
15
- # parse one or more comma-separated .env files
16
- require 'csv'
17
- CSV.parse_line argv.delete_at(pos)
18
- else
19
- []
20
- end
21
-
14
+ filenames = parse_filenames || []
22
15
  begin
23
- Dotenv.load! *filenames
16
+ Dotenv.load!(*filenames)
24
17
  rescue Errno::ENOENT => e
25
18
  abort e.message
26
19
  else
27
- exec *argv unless argv.empty?
20
+ exec(*argv) unless argv.empty?
28
21
  end
29
22
  end
23
+
24
+ private
25
+
26
+ def parse_filenames
27
+ pos = argv.index("-f")
28
+ return nil unless pos
29
+ # drop the -f
30
+ argv.delete_at pos
31
+ # parse one or more comma-separated .env files
32
+ require "csv"
33
+ CSV.parse_line argv.delete_at(pos)
34
+ end
30
35
  end
31
36
  end
@@ -1,4 +1,6 @@
1
1
  module Dotenv
2
+ # This class inherits from Hash and represents the environemnt into which
3
+ # Dotenv will load key value pairs from a file.
2
4
  class Environment < Hash
3
5
  attr_reader :filename
4
6
 
@@ -16,11 +18,11 @@ module Dotenv
16
18
  end
17
19
 
18
20
  def apply
19
- each { |k,v| ENV[k] ||= v }
21
+ each { |k, v| ENV[k] ||= v }
20
22
  end
21
23
 
22
24
  def apply!
23
- each { |k,v| ENV[k] = v }
25
+ each { |k, v| ENV[k] = v }
24
26
  end
25
27
  end
26
28
  end
data/lib/dotenv/parser.rb CHANGED
@@ -1,13 +1,15 @@
1
- require 'dotenv/substitutions/variable'
2
- if RUBY_VERSION > '1.8.7'
3
- require 'dotenv/substitutions/command'
4
- end
1
+ require "dotenv/substitutions/variable"
2
+ require "dotenv/substitutions/command" if RUBY_VERSION > "1.8.7"
5
3
 
6
4
  module Dotenv
7
5
  class FormatError < SyntaxError; end
8
6
 
7
+ # This class enables parsing of a string for key value pairs to be returned
8
+ # and stored in the Environment. It allows for variable substitutions and
9
+ # exporting of variables.
9
10
  class Parser
10
- @@substitutions = Substitutions.constants.map { |const| Substitutions.const_get(const) }
11
+ @substitutions =
12
+ Substitutions.constants.map { |const| Substitutions.const_get(const) }
11
13
 
12
14
  LINE = /
13
15
  \A
@@ -25,44 +27,67 @@ module Dotenv
25
27
  \z
26
28
  /x
27
29
 
28
- def self.call(string)
29
- new(string).call
30
+ class << self
31
+ attr_reader :substitutions
32
+
33
+ def call(string)
34
+ new(string).call
35
+ end
30
36
  end
31
37
 
32
38
  def initialize(string)
33
39
  @string = string
40
+ @hash = {}
34
41
  end
35
42
 
36
43
  def call
37
- @string.split("\n").inject({}) do |hash, line|
38
- if match = line.match(LINE)
39
- key, value = match.captures
44
+ @string.split("\n").each do |line|
45
+ parse_line(line)
46
+ end
47
+ @hash
48
+ end
49
+
50
+ private
40
51
 
41
- value ||= ''
42
- # Remove surrounding quotes
43
- value = value.strip.sub(/\A(['"])(.*)\1\z/, '\2')
52
+ def parse_line(line)
53
+ if (match = line.match(LINE))
54
+ key, value = match.captures
55
+ @hash[key] = parse_value(value || "")
56
+ elsif line.split.first == "export"
57
+ if variable_not_set?(line)
58
+ fail FormatError, "Line #{line.inspect} has an unset variable"
59
+ end
60
+ elsif line !~ /\A\s*(?:#.*)?\z/ # not comment or blank line
61
+ fail FormatError, "Line #{line.inspect} doesn't match format"
62
+ end
63
+ end
44
64
 
45
- if $1 == '"'
46
- value = value.gsub('\n', "\n")
47
- # Unescape all characters except $ so variables can be escaped properly
48
- value = value.gsub(/\\([^$])/, '\1')
49
- end
65
+ def parse_value(value)
66
+ # Remove surrounding quotes
67
+ value = value.strip.sub(/\A(['"])(.*)\1\z/, '\2')
50
68
 
51
- if $1 != "'"
52
- @@substitutions.each do |proc|
53
- value = proc.call(value, hash)
54
- end
55
- end
69
+ if Regexp.last_match(1) == '"'
70
+ value = unescape_characters(expand_newlines(value))
71
+ end
56
72
 
57
- hash[key] = value
58
- elsif line.split.first == 'export'
59
- # looks like you want to export after declaration, I guess that is ok
60
- raise FormatError, "Line #{line.inspect} has a variable that is not set" unless line.split[1..-1].all?{ |var| hash.member?(var) }
61
- elsif line !~ /\A\s*(?:#.*)?\z/ # not comment or blank line
62
- raise FormatError, "Line #{line.inspect} doesn't match format"
73
+ if Regexp.last_match(1) != "'"
74
+ self.class.substitutions.each do |proc|
75
+ value = proc.call(value, @hash)
63
76
  end
64
- hash
65
77
  end
78
+ value
79
+ end
80
+
81
+ def unescape_characters(value)
82
+ value.gsub(/\\([^$])/, '\1')
83
+ end
84
+
85
+ def expand_newlines(value)
86
+ value.gsub('\n', "\n")
87
+ end
88
+
89
+ def variable_not_set?(line)
90
+ !line.split[1..-1].all? { |var| @hash.member?(var) }
66
91
  end
67
92
  end
68
93
  end
@@ -1,3 +1,5 @@
1
+ require "English"
2
+
1
3
  module Dotenv
2
4
  module Substitutions
3
5
  # Substitute shell commands in a value.
@@ -6,26 +8,27 @@ module Dotenv
6
8
  #
7
9
  module Command
8
10
  class << self
9
-
10
11
  INTERPOLATED_SHELL_COMMAND = /
11
12
  (?<backslash>\\)? # is it escaped with a backslash?
12
13
  \$ # literal $
13
14
  (?<cmd> # collect command content for eval
14
15
  \( # require opening paren
15
- ([^()]|\g<cmd>)+ # allow any number of non-parens, or balanced parens (by nesting the <cmd> expression recursively)
16
+ ([^()]|\g<cmd>)+ # allow any number of non-parens, or balanced
17
+ # parens (by nesting the <cmd> expression
18
+ # recursively)
16
19
  \) # require closing paren
17
20
  )
18
21
  /x
19
22
 
20
- def call(value, env)
23
+ def call(value, _env)
21
24
  # Process interpolated shell commands
22
25
  value.gsub(INTERPOLATED_SHELL_COMMAND) do |*|
23
26
  # Eliminate opening and closing parentheses
24
- command = $~[:cmd][1..-2]
27
+ command = $LAST_MATCH_INFO[:cmd][1..-2]
25
28
 
26
- if $~[:backslash]
29
+ if $LAST_MATCH_INFO[:backslash]
27
30
  # Command is escaped, don't replace it.
28
- $~[0][1..-1]
31
+ $LAST_MATCH_INFO[0][1..-1]
29
32
  else
30
33
  # Execute the command and return the value
31
34
  `#{command}`.chomp
@@ -33,7 +36,6 @@ module Dotenv
33
36
  end
34
37
  end
35
38
  end
36
-
37
39
  end
38
40
  end
39
41
  end
@@ -7,7 +7,6 @@ module Dotenv
7
7
  #
8
8
  module Variable
9
9
  class << self
10
-
11
10
  VARIABLE = /
12
11
  (\\)? # is it escaped with a backslash?
13
12
  (\$) # literal $
@@ -23,20 +22,18 @@ module Dotenv
23
22
  value.scan(VARIABLE).each do |parts|
24
23
  if parts.first == '\\'
25
24
  # Variable is escaped, don't replace it.
26
- replace = parts[1...-1].join('')
25
+ replace = parts[1...-1].join("")
27
26
  else
28
27
  # Replace it with the value from the environment
29
28
  replace = env.fetch(parts.last) { ENV[parts.last] }
30
29
  end
31
30
 
32
- value = value.sub(parts[0...-1].join(''), replace || '')
31
+ value = value.sub(parts[0...-1].join(""), replace || "")
33
32
  end
34
33
 
35
34
  value
36
35
  end
37
36
  end
38
-
39
37
  end
40
-
41
38
  end
42
39
  end
data/lib/dotenv/tasks.rb CHANGED
@@ -1,7 +1,7 @@
1
- desc 'Load environment settings from .env'
1
+ desc "Load environment settings from .env"
2
2
  task :dotenv do
3
- require 'dotenv'
3
+ require "dotenv"
4
4
  Dotenv.load
5
5
  end
6
6
 
7
- task :environment => :dotenv
7
+ task :environment => :dotenv
@@ -1,3 +1,3 @@
1
1
  module Dotenv
2
- VERSION = '2.0.0.beta'
2
+ VERSION = "2.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotenv
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Keepers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-22 00:00:00.000000000 Z
11
+ date: 2015-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Loads environment variables from `.env`.
42
56
  email:
43
57
  - brandon@opensoul.org
@@ -72,9 +86,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
72
86
  version: '0'
73
87
  required_rubygems_version: !ruby/object:Gem::Requirement
74
88
  requirements:
75
- - - ">"
89
+ - - ">="
76
90
  - !ruby/object:Gem::Version
77
- version: 1.3.1
91
+ version: '0'
78
92
  requirements: []
79
93
  rubyforge_project:
80
94
  rubygems_version: 2.2.2