pax_global_header00006660000000000000000000000064125410305770014516gustar00rootroot0000000000000052 comment=b11bd50e0ba50a0ccdf6e79704ab7e2295568999 dotenv-2.0.2/000077500000000000000000000000001254103057700130165ustar00rootroot00000000000000dotenv-2.0.2/.gitignore000066400000000000000000000000741254103057700150070ustar00rootroot00000000000000*.gem *.rbc .bundle .config .yardoc Gemfile.lock tmp vendor dotenv-2.0.2/.rubocop.yml000066400000000000000000000005471254103057700152760ustar00rootroot00000000000000Lint/HandleExceptions: Exclude: - 'lib/dotenv/rails.rb' - 'lib/dotenv.rb' Style/Documentation: Exclude: - 'Rakefile' - 'lib/dotenv/version.rb' Style/FileName: Exclude: - 'lib/dotenv/rails-now.rb' - 'lib/dotenv-rails.rb' Style/HashSyntax: EnforcedStyle: 'hash_rockets' Style/StringLiterals: EnforcedStyle: 'double_quotes' dotenv-2.0.2/.travis.yml000066400000000000000000000003061254103057700151260ustar00rootroot00000000000000language: ruby rvm: - 2.2 - 2.1 - 2.0.0 - 1.9.3 - rbx-2 sudo: false bundler_args: --without=guard notifications: disabled: true script: - bundle exec rake - bundle exec rubocop dotenv-2.0.2/Changelog.md000066400000000000000000000123541254103057700152340ustar00rootroot00000000000000# Changelog ## 2.0.2 - June 19, 2015 * Support charriage returns in addition to newlines in .env ([#194](https://github.com/bkeepers/dotenv/pull/194)) * Add runtime dependency on rails 4 for dotenv-rails ([#189](https://github.com/bkeepers/dotenv/pull/189)) [Full Changelog](https://github.com/bkeepers/dotenv/compare/v2.0.1...v2.0.2) ## 2.0.1 - Apr 3, 2015 * Fix for expansion of escaped variables ([#181](https://github.com/bkeepers/dotenv/pull/181)) [Full Changelog](https://github.com/bkeepers/dotenv/compare/v2.0.0...v2.0.1) ## 2.0.0 - Mar 5, 2015 * `.env.local` and `.env.#{Rails.env}` will be automatically be loaded with the `dotenv-rails` gem. * Drop official support for Ruby 1.8.7 and REE. They may still continue to work, but will not be tested against. Lock to version "<= 1.1" if you are using Ruby 1.8. * `dotenv-rails` now only supports Rails 4. Manually configure dotenv if you are using Rails 3. * Support -f option to dotenv executable dotenv -f /path/to/.env,/path/to/another/.env * Fix issue calling `Dotenv::Railtie.load` in Rails 4.1 before application is defined (#155) [Full Changelog](https://github.com/bkeepers/dotenv/compare/v1.0.2...v2.0.0) ## 1.0.2 - Oct 14, 2014 * Define `#load` on `Dotenv::Railtie`, which can be called to manually load `dotenv` before Rails has initialized. * add `dotenv/rails-now`, which can be required in the `Gemfile` to immediately load dotenv. gem 'dotenv-rails', :require => 'dotenv/rails-now' gem 'gem-that-requires-env-variables' [Full Changelog](https://github.com/bkeepers/dotenv/compare/v1.0.1...v1.0.2) ## 1.0.1 - Oct 4, 2014 * Fix load error with Spring when running `rails server` ([#140](https://github.com/bkeepers/dotenv/issues/140)) [Full Changelog](https://github.com/bkeepers/dotenv/compare/v1.0.0...v1.0.1) ## 1.0.0 - Oct 3, 2014 * dotenv-rails is now loaded during the `before_configuration` callback, which is fired when the `Application` constant is defined (`class Application < Rails::Application`). * Remove deprecated features. Upgrade to 0.11.0 and fix deprecation warnings before upgrading to 1.0.0. * Watch .env for changes with Spring in Rails 4 ([#118](https://github.com/bkeepers/dotenv/pull/118)) * Fix deprecation warnings for `File.exists?` ([#121](https://github.com/bkeepers/dotenv/pull/121/)) * Use `Rails.root` to find `.env` ([#122](https://github.com/bkeepers/dotenv/pull/122/files)) * Avoid substitutions inside single quotes ([#124](https://github.com/bkeepers/dotenv/pull/124)) [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.11.1...v1.0.0) ## 0.11.1 - Apr 22, 2014 * Depend on dotenv-deployment ~>0.0.2, which fixes issues with 0.0.1 [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.11.0...v0.11.1) ## 0.11.0 - Apr 21, 2014 * Extract dotenv-deployment gem. https://github.com/bkeepers/dotenv-deployment [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.10.0...v0.11.0) ## 0.10.0 - Feb 22, 2014 * Add support for executing interpolated commands. (Ruby >= 1.9 only) HEAD_SHA=$(git rev-parse HEAD) * Add `dotenv_role` option in Capistrano. set :dotenv_role, [:app, web] * Add `Dotenv.overload` to overwrite existing environment values. [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.9.0...v0.10.0) ## 0.9.0 - Aug 29, 2013 * Add support for variable expansion. HOST="example.com" URL="http://${USER}@${HOST}" ESCAPED_VARIABLE="this is \$NOT replaced" * Allow setting variables without a value. BLANK= * Add `dotenv` executable to load `.env` for other scripts. $ dotenv ./script.py [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.8.0...v0.9.0) ## 0.8.0 - June 12, 2013 * Added a capistrano recipe to symlink in `.env` on deploy. * Allow inline comments VARIABLE=value # this is a comment * Raises Dotenv::FormatError when parsing fails [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.7.0...v0.8.0) ## 0.7.0 - April 15, 2013 * Remove deprectated autoloading. Upgrade to 0.6 first and fix any warnings. * Add Dotenv.load! which raises Errno::ENOENT if the file does not exist [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.6.0...v0.7.0) ## 0.6.0 - Mar 22, 2013 * Add dotenv-rails gem for autoloading in a Rails app * Deprecated autoloading with plain dotenv gem * Support for double quotes A="some value" B="with \"escaped\" quotes" C="and newline\n expansion" * Support for pow-style variables prefixed with export export VARIABLE="some value" [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.5.0...v0.6.0) ## 0.5.0 - Jan 25, 2013 * Load immediately on require in Rails instead of waiting for initialization * Add YAML-style variables VARIABLE: some value [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.4.0...v0.5.0) ## 0.4.0 - Nov 13, 2012 * Add support for quoted options, e.g.: VARIABLE='some value' * Fix rake deprecation warnings [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.3.0...v0.4.0) ## 0.3.0 - Oct 25, 2012 * Avoid overriding existing ENV variables so values set before loading the app are maintained. [Full Changelog](https://github.com/bkeepers/dotenv/compare/v0.2.0...v0.3.0) dotenv-2.0.2/Gemfile000066400000000000000000000004131254103057700143070ustar00rootroot00000000000000source "https://rubygems.org" gemspec :name => "dotenv" gemspec :name => "dotenv-rails" group :guard do gem "guard-rspec" gem "guard-bundler" gem "rb-fsevent" end platforms :rbx do gem "rubysl", "~> 2.0" # if using anything in the ruby standard library end dotenv-2.0.2/Guardfile000066400000000000000000000003551254103057700146460ustar00rootroot00000000000000guard "bundler" do watch("Gemfile") end guard "rspec", :cmd => "bundle exec rspec" do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^spec/spec_helper.rb$}) { "spec" } watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } end dotenv-2.0.2/LICENSE000066400000000000000000000020571254103057700140270ustar00rootroot00000000000000Copyright (c) 2012 Brandon Keepers MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.dotenv-2.0.2/README.md000066400000000000000000000127731254103057700143070ustar00rootroot00000000000000# dotenv [![Build Status](https://secure.travis-ci.org/bkeepers/dotenv.png?branch=master)](https://travis-ci.org/bkeepers/dotenv) [![Join the chat at https://gitter.im/bkeepers/dotenv](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bkeepers/dotenv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Shim to load environment variables from `.env` into `ENV` in *development*. Storing [configuration in the environment](http://www.12factor.net/config) is one of the tenets of a [twelve-factor app](http://www.12factor.net/). Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables. But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. dotenv loads variables from a `.env` file into `ENV` when the environment is bootstrapped. ## Installation ### Rails Add this line to the top of your application's Gemfile: ```ruby gem 'dotenv-rails', :groups => [:development, :test] ``` And then execute: ```shell $ bundle ``` #### Note on load order dotenv is initialized in your Rails app during the `before_configuration` callback, which is fired when the `Application` constant is defined in `config/application.rb` with `class Application < Rails::Application`. If you need it to be initialized sooner, you can manually call `Dotenv::Railtie.load`. ```ruby # config/application.rb Bundler.require(*Rails.groups) Dotenv::Railtie.load HOSTNAME = ENV['HOSTNAME'] ``` If you use gems that require environment variables to be set before they are loaded, then list `dotenv-rails` in the `Gemfile` before those other gems and require `dotenv/rails-now`. ```ruby gem 'dotenv-rails', :require => 'dotenv/rails-now' gem 'gem-that-requires-env-variables' ``` ### Sinatra or Plain ol' Ruby Install the gem: ```shell $ gem install dotenv ``` As early as possible in your application bootstrap process, load `.env`: ```ruby require 'dotenv' Dotenv.load ``` Alternatively, you can use the `dotenv` executable to launch your application: ```shell $ dotenv ./script.py ``` To ensure `.env` is loaded in rake, load the tasks: ```ruby require 'dotenv/tasks' task :mytask => :dotenv do # things that require .env end ``` ## Usage Add your application configuration to your `.env` file in the root of your project: ```shell S3_BUCKET=YOURS3BUCKET SECRET_KEY=YOURSECRETKEYGOESHERE ``` If you need multiline variables, for example private keys, you can double quote strings and use the `\n` character for newlines: ```shell PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nHkVN9…\n-----END DSA PRIVATE KEY-----\n" ``` You may also add `export` in front of each line so you can `source` the file in bash: ```shell export S3_BUCKET=YOURS3BUCKET export SECRET_KEY=YOURSECRETKEYGOESHERE ``` Whenever your application loads, these variables will be available in `ENV`: ```ruby config.fog_directory = ENV['S3_BUCKET'] ``` Comments may be added to your file as such: ```shell # This is a comment SECRET_KEY=YOURSECRETKEYGOESHERE # comment SECRET_HASH="something-with-a-#-hash" ``` Variable names may not contain the `#` symbol. Values can use the `#` if they are enclosed in quotes. ## Multiple Rails Environments 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. 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`. You can also use `.env.local` for local overrides. If you use this gem to handle env vars for multiple Rails environments (development, test, production, etc.), please note that env vars that are general to all environments should be stored in `.env`. Then, environment specific env vars should be stored in `.env.`. When you load a certain environment, dotenv will first load general env vars from `.env`, then load environment specific env vars from `.env.`. Variables defined in `.env.` will override any values set in `.env` or already defined in the environment. ## Should I commit my .env file? Credentials should only be accessible on the machines that need access to them. Never commit sensitive information to a repository that is not needed by every development machine and server. Personally, I prefer to commit the `.env` file with development-only settings. This makes it easy for other developers to get started on the project without compromising credentials for other environments. If you follow this advice, make sure that all the credentials for your development environment are different from your other deployments and that the development credentials do not have access to any confidential data. ## Contributing If you want a better idea of how dotenv works, check out the [Ruby Rogues Code Reading of dotenv](https://www.youtube.com/watch?v=lKmY_0uY86s). 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Added some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request dotenv-2.0.2/Rakefile000066400000000000000000000012751254103057700144700ustar00rootroot00000000000000#!/usr/bin/env rake require "bundler/gem_helper" namespace "dotenv" do Bundler::GemHelper.install_tasks :name => "dotenv" end namespace "dotenv-rails" do class DotenvRailsGemHelper < Bundler::GemHelper def guard_already_tagged; end # noop def tag_version; end # noop end DotenvRailsGemHelper.install_tasks :name => "dotenv-rails" end task :build => ["dotenv:build", "dotenv-rails:build"] task :install => ["dotenv:install", "dotenv-rails:install"] task :release => ["dotenv:release", "dotenv-rails:release"] require "rspec/core/rake_task" desc "Run all specs" RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = %w(--color) t.verbose = false end task :default => :spec dotenv-2.0.2/bin/000077500000000000000000000000001254103057700135665ustar00rootroot00000000000000dotenv-2.0.2/bin/dotenv000077500000000000000000000001041254103057700150060ustar00rootroot00000000000000#!/usr/bin/env ruby require "dotenv/cli" Dotenv::CLI.new(ARGV).run dotenv-2.0.2/dotenv-rails.gemspec000066400000000000000000000011751254103057700167760ustar00rootroot00000000000000require File.expand_path("../lib/dotenv/version", __FILE__) require "English" Gem::Specification.new "dotenv-rails", Dotenv::VERSION do |gem| gem.authors = ["Brandon Keepers"] gem.email = ["brandon@opensoul.org"] gem.description = gem.summary = "Autoload dotenv in Rails." gem.homepage = "https://github.com/bkeepers/dotenv" gem.license = "MIT" gem.files = `git ls-files lib | grep rails` .split($OUTPUT_RECORD_SEPARATOR) + ["README.md", "LICENSE"] gem.add_dependency "dotenv", Dotenv::VERSION gem.add_dependency "railties", "~>4.0" gem.add_development_dependency "spring" end dotenv-2.0.2/dotenv.gemspec000066400000000000000000000013131254103057700156600ustar00rootroot00000000000000require File.expand_path("../lib/dotenv/version", __FILE__) require "English" Gem::Specification.new "dotenv", Dotenv::VERSION do |gem| gem.authors = ["Brandon Keepers"] gem.email = ["brandon@opensoul.org"] gem.description = gem.summary = "Loads environment variables from `.env`." gem.homepage = "https://github.com/bkeepers/dotenv" gem.license = "MIT" gem.files = `git ls-files README.md LICENSE lib bin | grep -v rails` .split($OUTPUT_RECORD_SEPARATOR) gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) } gem.add_development_dependency "rake" gem.add_development_dependency "rspec" gem.add_development_dependency "rubocop" end dotenv-2.0.2/lib/000077500000000000000000000000001254103057700135645ustar00rootroot00000000000000dotenv-2.0.2/lib/dotenv-rails.rb000066400000000000000000000000271254103057700165170ustar00rootroot00000000000000require "dotenv/rails" dotenv-2.0.2/lib/dotenv.rb000066400000000000000000000027021254103057700154110ustar00rootroot00000000000000require "dotenv/parser" require "dotenv/environment" # The top level Dotenv module. The entrypoint for the application logic. module Dotenv class << self attr_accessor :instrumenter end module_function def load(*filenames) with(*filenames) do |f| ignoring_nonexistent_files do env = Environment.new(f) instrument("dotenv.load", :env => env) { env.apply } end end end # same as `load`, but raises Errno::ENOENT if any files don't exist def load!(*filenames) with(*filenames) do |f| env = Environment.new(f) instrument("dotenv.load", :env => env) { env.apply } end end # same as `load`, but will override existing values in `ENV` def overload(*filenames) with(*filenames) do |f| ignoring_nonexistent_files do env = Environment.new(f) instrument("dotenv.overload", :env => env) { env.apply! } end end end # Internal: Helper to expand list of filenames. # # Returns a hash of all the loaded environment variables. def with(*filenames, &block) filenames << ".env" if filenames.empty? filenames.reduce({}) do |hash, filename| hash.merge! block.call(File.expand_path(filename)) || {} end end def instrument(name, payload = {}, &block) if instrumenter instrumenter.instrument(name, payload, &block) else block.call end end def ignoring_nonexistent_files yield rescue Errno::ENOENT end end dotenv-2.0.2/lib/dotenv/000077500000000000000000000000001254103057700150635ustar00rootroot00000000000000dotenv-2.0.2/lib/dotenv/cli.rb000066400000000000000000000013071254103057700161600ustar00rootroot00000000000000require "dotenv" module Dotenv # The CLI is a class responsible of handling all the command line interface # logic. class CLI attr_reader :argv def initialize(argv = []) @argv = argv.dup end def run filenames = parse_filenames || [] begin Dotenv.load!(*filenames) rescue Errno::ENOENT => e abort e.message else exec(*argv) unless argv.empty? end end private def parse_filenames pos = argv.index("-f") return nil unless pos # drop the -f argv.delete_at pos # parse one or more comma-separated .env files require "csv" CSV.parse_line argv.delete_at(pos) end end end dotenv-2.0.2/lib/dotenv/environment.rb000066400000000000000000000007601254103057700177570ustar00rootroot00000000000000module Dotenv # This class inherits from Hash and represents the environemnt into which # Dotenv will load key value pairs from a file. class Environment < Hash attr_reader :filename def initialize(filename) @filename = filename load end def load update Parser.call(read) end def read File.read(@filename) end def apply each { |k, v| ENV[k] ||= v } end def apply! each { |k, v| ENV[k] = v } end end end dotenv-2.0.2/lib/dotenv/parser.rb000066400000000000000000000045161254103057700167120ustar00rootroot00000000000000require "dotenv/substitutions/variable" require "dotenv/substitutions/command" if RUBY_VERSION > "1.8.7" module Dotenv class FormatError < SyntaxError; end # This class enables parsing of a string for key value pairs to be returned # and stored in the Environment. It allows for variable substitutions and # exporting of variables. class Parser @substitutions = Substitutions.constants.map { |const| Substitutions.const_get(const) } LINE = / \A (?:export\s+)? # optional export ([\w\.]+) # key (?:\s*=\s*|:\s+?) # separator ( # optional value begin '(?:\'|[^'])*' # single quoted value | # or "(?:\"|[^"])*" # double quoted value | # or [^#\n]+ # unquoted value )? # value end (?:\s*\#.*)? # optional comment \z /x class << self attr_reader :substitutions def call(string) new(string).call end end def initialize(string) @string = string @hash = {} end def call @string.split(/[\n\r]+/).each do |line| parse_line(line) end @hash end private def parse_line(line) if (match = line.match(LINE)) key, value = match.captures @hash[key] = parse_value(value || "") elsif line.split.first == "export" if variable_not_set?(line) fail FormatError, "Line #{line.inspect} has an unset variable" end elsif line !~ /\A\s*(?:#.*)?\z/ # not comment or blank line fail FormatError, "Line #{line.inspect} doesn't match format" end end def parse_value(value) # Remove surrounding quotes value = value.strip.sub(/\A(['"])(.*)\1\z/, '\2') if Regexp.last_match(1) == '"' value = unescape_characters(expand_newlines(value)) end if Regexp.last_match(1) != "'" self.class.substitutions.each do |proc| value = proc.call(value, @hash) end end value end def unescape_characters(value) value.gsub(/\\([^$])/, '\1') end def expand_newlines(value) value.gsub('\n', "\n").gsub('\r', "\r") end def variable_not_set?(line) !line.split[1..-1].all? { |var| @hash.member?(var) } end end end dotenv-2.0.2/lib/dotenv/rails-now.rb000066400000000000000000000005231254103057700173230ustar00rootroot00000000000000# If you use gems that require environment variables to be set before they are # loaded, then list `dotenv-rails` in the `Gemfile` before those other gems and # require `dotenv/rails-now`. # # gem "dotenv-rails", :require => "dotenv/rails-now" # gem "gem-that-requires-env-variables" # require "dotenv/rails" Dotenv::Railtie.load dotenv-2.0.2/lib/dotenv/rails.rb000066400000000000000000000025611254103057700165260ustar00rootroot00000000000000require "dotenv" Dotenv.instrumenter = ActiveSupport::Notifications # Watch all loaded env files with Spring begin require "spring/watcher" ActiveSupport::Notifications.subscribe(/^dotenv/) do |*args| event = ActiveSupport::Notifications::Event.new(*args) Spring.watch event.payload[:env].filename if Rails.application end rescue LoadError # Spring is not available end module Dotenv # Dotenv Railtie for using Dotenv to load environment from a file into # Rails applications class Railtie < Rails::Railtie config.before_configuration { load } # Public: Load dotenv # # This will get called during the `before_configuration` callback, but you # can manually call `Dotenv::Railtie.load` if you needed it sooner. def load Dotenv.load( root.join(".env.local"), root.join(".env.#{Rails.env}"), root.join(".env") ) end # Internal: `Rails.root` is nil in Rails 4.1 before the application is # initialized, so this falls back to the `RAILS_ROOT` environment variable, # or the current working directory. def root Rails.root || Pathname.new(ENV["RAILS_ROOT"] || Dir.pwd) end # Rails uses `#method_missing` to delegate all class methods to the # instance, which means `Kernel#load` gets called here. We don't want that. def self.load instance.load end end end dotenv-2.0.2/lib/dotenv/substitutions/000077500000000000000000000000001254103057700200225ustar00rootroot00000000000000dotenv-2.0.2/lib/dotenv/substitutions/command.rb000066400000000000000000000023771254103057700217760ustar00rootroot00000000000000require "English" module Dotenv module Substitutions # Substitute shell commands in a value. # # SHA=$(git rev-parse HEAD) # module Command class << self INTERPOLATED_SHELL_COMMAND = / (?\\)? # is it escaped with a backslash? \$ # literal $ (? # collect command content for eval \( # require opening paren ([^()]|\g)+ # allow any number of non-parens, or balanced # parens (by nesting the expression # recursively) \) # require closing paren ) /x def call(value, _env) # Process interpolated shell commands value.gsub(INTERPOLATED_SHELL_COMMAND) do |*| # Eliminate opening and closing parentheses command = $LAST_MATCH_INFO[:cmd][1..-2] if $LAST_MATCH_INFO[:backslash] # Command is escaped, don't replace it. $LAST_MATCH_INFO[0][1..-1] else # Execute the command and return the value `#{command}`.chomp end end end end end end end dotenv-2.0.2/lib/dotenv/substitutions/variable.rb000066400000000000000000000014001254103057700221270ustar00rootroot00000000000000require "English" module Dotenv module Substitutions # Substitute variables in a value. # # HOST=example.com # URL="https://$HOST" # module Variable class << self VARIABLE = / (\\)? # is it escaped with a backslash? (\$) # literal $ \{? # allow brace wrapping ([A-Z0-9_]+) # match the variable \}? # closing brace /xi def call(value, env) value.gsub(VARIABLE) do |variable| match = $LAST_MATCH_INFO if match[1] == '\\' variable[1..-1] else env.fetch(match[3]) { ENV[match[3]] } end end end end end end end dotenv-2.0.2/lib/dotenv/tasks.rb000066400000000000000000000001761254103057700165410ustar00rootroot00000000000000desc "Load environment settings from .env" task :dotenv do require "dotenv" Dotenv.load end task :environment => :dotenv dotenv-2.0.2/lib/dotenv/version.rb000066400000000000000000000000461254103057700170750ustar00rootroot00000000000000module Dotenv VERSION = "2.0.2" end dotenv-2.0.2/spec/000077500000000000000000000000001254103057700137505ustar00rootroot00000000000000dotenv-2.0.2/spec/dotenv/000077500000000000000000000000001254103057700152475ustar00rootroot00000000000000dotenv-2.0.2/spec/dotenv/cli_spec.rb000066400000000000000000000022661254103057700173630ustar00rootroot00000000000000require "spec_helper" require "dotenv/cli" describe "dotenv binary" do before do Dir.chdir(File.expand_path("../../fixtures", __FILE__)) end def run(*args) Dotenv::CLI.new(args).run end it "loads from .env by default" do expect(ENV).not_to have_key("DOTENV") run expect(ENV).to have_key("DOTENV") end it "loads from file specified by -f" do expect(ENV).not_to have_key("OPTION_A") run "-f", "plain.env" expect(ENV).to have_key("OPTION_A") end it "dies if file specified by -f doesn't exist" do expect do capture_output { run "-f", ".doesnotexist" } end.to raise_error(SystemExit, /No such file/) end it "loads from multiple files specified by -f" do expect(ENV).not_to have_key("PLAIN") expect(ENV).not_to have_key("QUOTED") run "-f", "plain.env,quoted.env" expect(ENV).to have_key("PLAIN") expect(ENV).to have_key("QUOTED") end # Capture output to $stdout and $stderr def capture_output(&_block) original_stderr = $stderr original_stdout = $stdout output = $stderr = $stdout = StringIO.new yield $stderr = original_stderr $stdout = original_stdout output.string end end dotenv-2.0.2/spec/dotenv/environment_spec.rb000066400000000000000000000022401254103057700211500ustar00rootroot00000000000000require "spec_helper" describe Dotenv::Environment do subject { env("OPTION_A=1\nOPTION_B=2") } describe "initialize" do it "reads the file" do expect(subject["OPTION_A"]).to eq("1") expect(subject["OPTION_B"]).to eq("2") end it "fails if file does not exist" do expect do Dotenv::Environment.new(".does_not_exists") end.to raise_error(Errno::ENOENT) end end describe "apply" do it "sets variables in ENV" do subject.apply expect(ENV["OPTION_A"]).to eq("1") end it "does not override defined variables" do ENV["OPTION_A"] = "predefined" subject.apply expect(ENV["OPTION_A"]).to eq("predefined") end end describe "apply!" do it "sets variables in the ENV" do subject.apply! expect(ENV["OPTION_A"]).to eq("1") end it "overrides defined variables" do ENV["OPTION_A"] = "predefined" subject.apply! expect(ENV["OPTION_A"]).to eq("1") end end require "tempfile" def env(text) file = Tempfile.new("dotenv") file.write text file.close env = Dotenv::Environment.new(file.path) file.unlink env end end dotenv-2.0.2/spec/dotenv/parser_spec.rb000066400000000000000000000120041254103057700200770ustar00rootroot00000000000000require "spec_helper" describe Dotenv::Parser do def env(string) Dotenv::Parser.call(string) end it "parses unquoted values" do expect(env("FOO=bar")).to eql("FOO" => "bar") end it "parses values with spaces around equal sign" do expect(env("FOO =bar")).to eql("FOO" => "bar") expect(env("FOO= bar")).to eql("FOO" => "bar") end it "parses double quoted values" do expect(env('FOO="bar"')).to eql("FOO" => "bar") end it "parses single quoted values" do expect(env("FOO='bar'")).to eql("FOO" => "bar") end it "parses escaped double quotes" do expect(env('FOO="escaped\"bar"')).to eql("FOO" => 'escaped"bar') end it "parses empty values" do expect(env("FOO=")).to eql("FOO" => "") end it "expands variables found in values" do expect(env("FOO=test\nBAR=$FOO")).to eql("FOO" => "test", "BAR" => "test") end it "parses variables wrapped in brackets" do expect(env("FOO=test\nBAR=${FOO}bar")) .to eql("FOO" => "test", "BAR" => "testbar") end it "reads variables from ENV when expanding if not found in local env" do ENV["FOO"] = "test" expect(env("BAR=$FOO")).to eql("BAR" => "test") end it "expands undefined variables to an empty string" do expect(env("BAR=$FOO")).to eql("BAR" => "") end it "expands variables in double quoted strings" do expect(env("FOO=test\nBAR=\"quote $FOO\"")) .to eql("FOO" => "test", "BAR" => "quote test") end it "does not expand variables in single quoted strings" do expect(env("BAR='quote $FOO'")).to eql("BAR" => "quote $FOO") end it "does not expand escaped variables" do expect(env('FOO="foo\$BAR"')).to eql("FOO" => "foo$BAR") expect(env('FOO="foo\${BAR}"')).to eql("FOO" => "foo${BAR}") expect(env("FOO=test\nBAR=\"foo\\${FOO} ${FOO}\"")) .to eql("FOO" => "test", "BAR" => "foo${FOO} test") end it "parses yaml style options" do expect(env("OPTION_A: 1")).to eql("OPTION_A" => "1") end it "parses export keyword" do expect(env("export OPTION_A=2")).to eql("OPTION_A" => "2") end it "allows export line if you want to do it that way" do expect(env('OPTION_A=2 export OPTION_A')).to eql("OPTION_A" => "2") end it "allows export line if you want to do it that way and checks for unset"\ " variables" do expect do env('OPTION_A=2 export OH_NO_NOT_SET') end.to raise_error(Dotenv::FormatError, 'Line "export OH_NO_NOT_SET"'\ " has an unset variable") end it "expands newlines in quoted strings" do expect(env('FOO="bar\nbaz"')).to eql("FOO" => "bar\nbaz") end it 'parses variables with "." in the name' do expect(env("FOO.BAR=foobar")).to eql("FOO.BAR" => "foobar") end it "strips unquoted values" do expect(env("foo=bar ")).to eql("foo" => "bar") # not 'bar ' end it "throws an error if line format is incorrect" do expect { env("lol$wut") }.to raise_error(Dotenv::FormatError) end it "ignores empty lines" do expect(env("\n \t \nfoo=bar\n \nfizz=buzz")) .to eql("foo" => "bar", "fizz" => "buzz") end it "ignores inline comments" do expect(env("foo=bar # this is foo")).to eql("foo" => "bar") end it "allows # in quoted value" do expect(env('foo="bar#baz" # comment')).to eql("foo" => "bar#baz") end it "ignores comment lines" do expect(env("\n\n\n # HERE GOES FOO \nfoo=bar")).to eql("foo" => "bar") end it "parses # in quoted values" do expect(env('foo="ba#r"')).to eql("foo" => "ba#r") expect(env("foo='ba#r'")).to eql("foo" => "ba#r") end if RUBY_VERSION > "1.8.7" it "parses shell commands interpolated in $()" do expect(env("ruby_v=$(ruby -v)")).to eql("ruby_v" => RUBY_DESCRIPTION) end it "allows balanced parentheses within interpolated shell commands" do expect(env('ruby_v=$(echo "$(echo "$(echo "$(ruby -v)")")")')) .to eql("ruby_v" => RUBY_DESCRIPTION) end it "doesn't interpolate shell commands when escape says not to" do expect(env('ruby_v=escaped-\$(ruby -v)')) .to eql("ruby_v" => "escaped-$(ruby -v)") end it "is not thrown off by quotes in interpolated shell commands" do expect(env('interp=$(echo "Quotes won\'t be a problem")')["interp"]) .to eql("Quotes won't be a problem") end it "supports carriage return" do expect(env("FOO=bar\rbaz=fbb")).to eql("FOO" => "bar", "baz" => "fbb") end it "supports carriage return combine with new line" do expect(env("FOO=bar\r\nbaz=fbb")).to eql("FOO" => "bar", "baz" => "fbb") end it "expands carriage return in quoted strings" do expect(env('FOO="bar\rbaz"')).to eql("FOO" => "bar\rbaz") end # This functionality is not supported on JRuby or Rubinius if (!defined?(RUBY_ENGINE) || RUBY_ENGINE != "jruby") && !defined?(Rubinius) it "substitutes shell variables within interpolated shell commands" do expect(env(%(VAR1=var1\ninterp=$(echo "VAR1 is $VAR1")))["interp"]) .to eql("VAR1 is var1") end end end end dotenv-2.0.2/spec/dotenv/rails_spec.rb000066400000000000000000000033261254103057700177240ustar00rootroot00000000000000require "spec_helper" ENV["RAILS_ENV"] = "test" require "rails" require "dotenv/rails" describe Dotenv::Railtie do # Fake watcher for Spring class SpecWatcher attr_reader :items def initialize @items = [] end def add(*items) @items |= items end end before do allow(Rails).to receive(:root) .and_return Pathname.new(File.expand_path("../../fixtures", __FILE__)) Rails.application = double(:application) Spring.watcher = SpecWatcher.new end after do # Reset Spring.watcher = nil Rails.application = nil end context "before_configuration" do it "calls #load" do expect(Dotenv::Railtie.instance).to receive(:load) ActiveSupport.run_load_hooks(:before_configuration) end end context "load" do before { Dotenv::Railtie.load } it "watches .env with Spring" do expect(Spring.watcher.items).to include(Rails.root.join(".env").to_s) end it "watches other loaded files with Spring" do path = fixture_path("plain.env") Dotenv.load(path) expect(Spring.watcher.items).to include(path) end it "loads .env, .env.local, and .env.#{Rails.env}" do expect(Spring.watcher.items).to eql([ Rails.root.join(".env.local").to_s, Rails.root.join(".env.test").to_s, Rails.root.join(".env").to_s ]) end it "loads .env.local before .env" do expect(ENV["DOTENV"]).to eql("local") end context "when Rails.root is nil" do before do allow(Rails).to receive(:root).and_return(nil) end it "falls back to RAILS_ROOT" do ENV["RAILS_ROOT"] = "/tmp" expect(Dotenv::Railtie.root.to_s).to eql("/tmp") end end end end dotenv-2.0.2/spec/dotenv_spec.rb000066400000000000000000000066031254103057700166130ustar00rootroot00000000000000require "spec_helper" describe Dotenv do before do Dir.chdir(File.expand_path("../fixtures", __FILE__)) end shared_examples "load" do context "with no args" do let(:env_files) { [] } it "defaults to .env" do expect(Dotenv::Environment).to receive(:new).with(expand(".env")) .and_return(double(:apply => {}, :apply! => {})) subject end end context "with a tilde path" do let(:env_files) { ["~/.env"] } it "expands the path" do expected = expand("~/.env") allow(File).to receive(:exist?) { |arg| arg == expected } expect(Dotenv::Environment).to receive(:new).with(expected) .and_return(double(:apply => {}, :apply! => {})) subject end end context "with multiple files" do let(:env_files) { [".env", fixture_path("plain.env")] } let(:expected) do { "OPTION_A" => "1", "OPTION_B" => "2", "OPTION_C" => "3", "OPTION_D" => "4", "OPTION_E" => "5", "PLAIN" => "true", "DOTENV" => "true" } end it "loads all files" do subject expected.each do |key, value| expect(ENV[key]).to eq(value) end end it "returns hash of loaded environments" do expect(subject).to eq(expected) end end end describe "load" do subject { Dotenv.load(*env_files) } it_behaves_like "load" context "when the file does not exist" do let(:env_files) { [".env_does_not_exist"] } it "fails silently" do expect { subject }.not_to raise_error expect(ENV.keys).to eq(@env_keys) end end end describe "load!" do subject { Dotenv.load!(*env_files) } it_behaves_like "load" context "when one file exists and one does not" do let(:env_files) { [".env", ".env_does_not_exist"] } it "raises an Errno::ENOENT error" do expect { subject }.to raise_error(Errno::ENOENT) end end end describe "overload" do let(:env_files) { [fixture_path("plain.env")] } subject { Dotenv.overload(*env_files) } it_behaves_like "load" context "when loading a file containing already set variables" do let(:env_files) { [fixture_path("plain.env")] } it "overrides any existing ENV variables" do ENV["OPTION_A"] = "predefined" subject expect(ENV["OPTION_A"]).to eq("1") end end context "when the file does not exist" do let(:env_files) { [".env_does_not_exist"] } it "fails silently" do expect { subject }.not_to raise_error expect(ENV.keys).to eq(@env_keys) end end end describe "with an instrumenter" do let(:instrumenter) { double("instrumenter", :instrument => {}) } before { Dotenv.instrumenter = instrumenter } after { Dotenv.instrumenter = nil } describe "load" do it "instruments if the file exists" do expect(instrumenter).to receive(:instrument) do |name, payload| expect(name).to eq("dotenv.load") expect(payload[:env]).to be_instance_of(Dotenv::Environment) {} end Dotenv.load end it "does not instrument if file does not exist" do expect(instrumenter).to receive(:instrument).never Dotenv.load ".doesnotexist" end end end def expand(path) File.expand_path path end end dotenv-2.0.2/spec/fixtures/000077500000000000000000000000001254103057700156215ustar00rootroot00000000000000dotenv-2.0.2/spec/fixtures/.env000066400000000000000000000000141254103057700164050ustar00rootroot00000000000000DOTENV=true dotenv-2.0.2/spec/fixtures/.env.local000066400000000000000000000000351254103057700175010ustar00rootroot00000000000000FROM_LOCAL=true DOTENV=local dotenv-2.0.2/spec/fixtures/.env.test000066400000000000000000000000311254103057700173620ustar00rootroot00000000000000FROM_RAILS_ENV=.env.test dotenv-2.0.2/spec/fixtures/exported.env000066400000000000000000000000471254103057700201660ustar00rootroot00000000000000export OPTION_A=2 export OPTION_B='\n' dotenv-2.0.2/spec/fixtures/plain.env000066400000000000000000000001061254103057700174330ustar00rootroot00000000000000PLAIN=true OPTION_A=1 OPTION_B=2 OPTION_C= 3 OPTION_D =4 OPTION_E = 5 dotenv-2.0.2/spec/fixtures/quoted.env000066400000000000000000000001641254103057700176350ustar00rootroot00000000000000QUOTED=true OPTION_A='1' OPTION_B='2' OPTION_C='' OPTION_D='\n' OPTION_E="1" OPTION_F="2" OPTION_G="" OPTION_H="\n" dotenv-2.0.2/spec/fixtures/yaml.env000066400000000000000000000000661254103057700172770ustar00rootroot00000000000000OPTION_A: 1 OPTION_B: '2' OPTION_C: '' OPTION_D: '\n' dotenv-2.0.2/spec/spec_helper.rb000066400000000000000000000004461254103057700165720ustar00rootroot00000000000000require "dotenv" RSpec.configure do |config| # Restore the state of ENV after each spec config.before { @env_keys = ENV.keys } config.after { ENV.delete_if { |k, _v| !@env_keys.include?(k) } } end def fixture_path(name) File.join(File.expand_path("../fixtures", __FILE__), name) end