dotenv 2.0.0.beta → 2.0.0

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 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