envandle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6ca4f6faadb9b5212f25212d23ab42ab36d9e1c5
4
+ data.tar.gz: 00da2b9a9de635373d09654e47f52c391b28b6ba
5
+ SHA512:
6
+ metadata.gz: 98977a5f9a1f7b29e0b1222693cf6f04cb8ea409ab1c31aa3ac67bf7fed328cda2b6818f31c6690ce62395f937c76754ecce5388d0514b1804c851639b4c50ab
7
+ data.tar.gz: 2f70f6b8b345f854c8fffe4791ba47e56b432d7602136c1f91c4cb523dc9d702db1ffd03be287b8fa67d1f451b5f03f50801389ff7915a7aa9870df2f547bdcf
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in envandle.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Envandle
2
+
3
+ A rubygem for enabling Gemfiles to specify gem locations from environment variables.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ $ gem install envandle
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Write a Gemfile.
14
+
15
+ ```ruby
16
+ require "envandle"
17
+
18
+ source "https://rubygems.org"
19
+
20
+ binding.envandle do |bundle|
21
+ bundle.gem "mygem", "~> 1.0"
22
+ end
23
+ ```
24
+
25
+ Set the environment variables.
26
+
27
+ ```sh
28
+ export ENVANDLE_GEM_PATH=mygem:/path/to/mygem
29
+ ```
30
+
31
+ And execute Bundler.
32
+
33
+ ```sh
34
+ $ bundle
35
+ ```
36
+
37
+ ## Examples
38
+
39
+ ### Setting Paths
40
+
41
+ You can specify the gem method's `path` option by setting the ENVANDLE_GEM_PATH variable.
42
+
43
+ For example,
44
+
45
+ ```ruby
46
+ ENV["ENVANDLE_GEM_PATH"] = "mygem:/path/to/mygem"
47
+
48
+ binding.envandle do |bundle|
49
+ bundle.gem "mygem", "~> 1.0"
50
+ end
51
+ ```
52
+
53
+ is evaluated as:
54
+
55
+ ```ruby
56
+ gem "mygem", path: "/path/to/mygem"
57
+ ```
58
+
59
+ If the variable is not set,
60
+
61
+ ```ruby
62
+ ENV["ENVANDLE_GEM_PATH"] = ""
63
+
64
+ binding.envandle do |bundle|
65
+ bundle.gem "mygem", "~> 1.0"
66
+ end
67
+ ```
68
+
69
+ is evaluated as:
70
+
71
+ ```ruby
72
+ gem "mygem", "~> 1.0"
73
+ ```
74
+
75
+ ### Setting Git Branches
76
+
77
+ You can specify the gem method's `git` and `branch` options by setting the ENVANDLE_GEM_GIT_BRANCH variable.
78
+
79
+ For example,
80
+
81
+ ```ruby
82
+ ENV["ENVANDLE_GEM_GIT_BRANCH"] = "mygem:https://github.com/mosop/mygem.git#edge"
83
+
84
+ binding.envandle do |bundle|
85
+ bundle.gem "mygem", "~> 1.0"
86
+ end
87
+ ```
88
+
89
+ is evaluated as:
90
+
91
+ ```ruby
92
+ gem "mygem", git: "https://github.com/mosop/mygem.git", branch: "edge"
93
+ ```
94
+
95
+ If the variable is not set,
96
+
97
+ ```ruby
98
+ ENV["ENVANDLE_GEM_GIT_BRANCH"] = ""
99
+
100
+ binding.envandle do |bundle|
101
+ bundle.gem "mygem", "~> 1.0"
102
+ end
103
+ ```
104
+
105
+ is evaluated as:
106
+
107
+ ```ruby
108
+ gem "mygem", "~> 1.0"
109
+ ```
110
+
111
+ ### Specifying Gemspecs
112
+
113
+ As well as the regular Gemfile, you can also specify a gemspec not a single gem.
114
+
115
+ For example, if your gem's name is "mygem", the gemspec refers the a, b and c gems and the c's version requirement is "~> 1.0",
116
+
117
+ ```ruby
118
+ ENV["ENVANDLE_GEM_PATH"] = "a:/path/to/a;b:/path/to/b"
119
+
120
+ binding.envandle do |bundle|
121
+ bundle.gemspec
122
+ end
123
+ ```
124
+
125
+ is evaluated as:
126
+
127
+ ```ruby
128
+ gem "mygem", path: "."
129
+ gem "a", path: "/path/to/a"
130
+ gem "b", path: "/path/to/b"
131
+ gem "c", "~> 1.0"
132
+ ```
133
+
134
+ ### Resolving Multilevel Dependencies
135
+
136
+ For example, if a Gemfile refers the gem a that depends on the gem b, Envandle also tries to resolve the b's reference by the environment variables.
137
+
138
+ ```ruby
139
+ ENV["ENVANDLE_GEM_PATH"] = "a:/path/to/a;b:/path/to/b"
140
+
141
+ binding.envandle do |bundle|
142
+ bundle.gem "a", "~> 1.0"
143
+ end
144
+ ```
145
+
146
+ is evaluated as:
147
+
148
+ ```ruby
149
+ gem "a", path: "/path/to/a"
150
+ gem "b", path: "/path/to/b"
151
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "envandle"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/envandle.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'envandle/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "envandle"
8
+ spec.version = Envandle::VERSION
9
+ spec.authors = ["mosop"]
10
+
11
+ spec.summary = %q{A library for enabling Gemfiles to specify gem locations from environment variables.}
12
+ spec.homepage = "https://github.com/mosop/envandle"
13
+
14
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
15
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
16
+ if spec.respond_to?(:metadata)
17
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
18
+ else
19
+ raise "RubyGems 2.0 or newer is required to protect against " \
20
+ "public gem pushes."
21
+ end
22
+
23
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
+ f.match(%r{^(test|spec|features)/})
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.13"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rspec", "~> 3.5"
33
+ end
@@ -0,0 +1,10 @@
1
+ module Envandle
2
+ module AsGitReference
3
+ def self.extended(mod)
4
+ mod.extend AsReference
5
+ mod.class_eval do
6
+ attr_reader :url, :ref
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Envandle
2
+ module AsReference
3
+ def self.extended(mod)
4
+ mod.class_eval do
5
+ attr_reader :group, :name
6
+
7
+ def key
8
+ @key ||= ReferenceCache.key(group, name)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ require "envandle/lib"
2
+
3
+ class Binding
4
+ def envandle
5
+ /^(.+?):(\d+)(?::in `(.*)')?/ =~ caller(1, 1).first
6
+ yield ::Envandle::BundleDsl.new(::Envandle::Gemfile.new($1, self))
7
+ end
8
+
9
+ def gem(*args)
10
+ receiver.__send__ :gem, *args
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ module Envandle
2
+ class BundleDsl
3
+ def initialize(gemfile)
4
+ @gemfile = gemfile
5
+ end
6
+
7
+ def gem(*args)
8
+ @gemfile.gem nil, *args
9
+ end
10
+
11
+ def group(name)
12
+ yield GroupDsl.new(@gemfile, name)
13
+ end
14
+
15
+ def gemspec(development_group: "development", path: nil, name: nil)
16
+ development_group = development_group.to_s.strip
17
+ raise "No gemspec's development group." if development_group.empty?
18
+ name = name.to_s.strip if name
19
+ raise "No gemspec's name." if name && name.empty
20
+ path ||= Gemspec.find_file(@gemfile.dir, name: name)
21
+ path = path.to_s.strip
22
+ raise "No gemspec's path." if path.empty?
23
+ spec = Gemspec.new(path)
24
+ @gemfile.gem nil, spec.name, path: "."
25
+ spec.dependencies.each do |i|
26
+ group = i.type == :development ? development_group : nil
27
+ @gemfile.gem group, i.name, *i.requirements_list
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ module Envandle
2
+ class Gem
3
+ def initialize(group, name, args, options)
4
+ @group = group
5
+ @name = name
6
+ @args = args
7
+ @options = options
8
+ end
9
+
10
+ def args
11
+ h = @group ? {group: @group} : {}
12
+ h.merge! @options
13
+ if h.empty?
14
+ [@name, *@args]
15
+ else
16
+ [@name, *@args, h]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,48 @@
1
+ module Envandle
2
+ class Gemfile
3
+ def initialize(path, binding)
4
+ @path = path
5
+ @binding = binding
6
+ end
7
+
8
+ def dir
9
+ @dir ||= File.dirname(@path)
10
+ end
11
+
12
+ def gems
13
+ @gems ||= {}
14
+ end
15
+
16
+ def references
17
+ @references ||= ReferenceCache.new
18
+ end
19
+
20
+ def append(group, name, args, options)
21
+ key = ReferenceCache.key(group, name)
22
+ gems[key] || begin
23
+ if ref = references.find(key, name)
24
+ gem = ref.to_gem(args, options)
25
+ gems[key] = gem
26
+ ref.spec.runtime_dependencies.each do |i|
27
+ append nil, i.name, [], {}
28
+ end
29
+ @binding.gem *gem.args
30
+ else
31
+ gems[key] = gem = Gem.new(group, name, args, options)
32
+ @binding.gem *gem.args
33
+ end
34
+ end
35
+ end
36
+
37
+ def gem(group, *args)
38
+ h = args.last.is_a?(Hash) ? args.pop : {}
39
+ options = {}
40
+ h.each do |k, v|
41
+ options[k.to_s.to_sym] = v
42
+ end
43
+ name = args.shift.to_s.strip
44
+ raise "No gem name." if name.empty?
45
+ append group, name, args, options
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ module Envandle
2
+ class Gemspec
3
+ def initialize(path)
4
+ @path = path
5
+ @native = ::Gem::Specification.load(path)
6
+ end
7
+
8
+ def self.find_file(dir, name:)
9
+ name ||= "*"
10
+ Dir.glob(File.join(dir, "#{name}.gemspec")) do |f|
11
+ return f
12
+ end
13
+ nil
14
+ end
15
+
16
+ def name
17
+ @native.name
18
+ end
19
+
20
+ def dependencies
21
+ @native.dependencies
22
+ end
23
+
24
+ def runtime_dependencies
25
+ @native.runtime_dependencies
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module Envandle
2
+ GIT = `which git`.chomp
3
+
4
+ def self.git_pull(url, ref, branch)
5
+ raise "No git installed." if GIT.empty?
6
+ Dir.mktmpdir do |tmp|
7
+ Dir.chdir(tmp) do
8
+ sh "#{GIT} init"
9
+ sh "#{GIT} remote add origin #{url}"
10
+ sh "#{GIT} checkout -b #{branch}"
11
+ sh "#{GIT} pull origin #{ref}:#{branch}"
12
+ yield tmp
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ module Envandle
2
+ class GitBranchReference
3
+ extend AsGitReference
4
+
5
+ def initialize(group, name, url, ref)
6
+ @group = group
7
+ @name = name
8
+ @url = url
9
+ @ref = ref
10
+ end
11
+
12
+ def to_gem(args, options)
13
+ Gem.new(@group, @name, [], {git: @url, branch: @ref})
14
+ end
15
+
16
+ def spec
17
+ Envandle.git_pull(@url, @ref, @ref) do |dir|
18
+ Gemspec.new(File.join(dir, "#{@name}.gemspec"))
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Envandle
2
+ class GroupDsl
3
+ def initialize(world, name)
4
+ @world = world
5
+ name = name.to_s.strip
6
+ raise "No group name." if name.empty?
7
+ @name = name
8
+ end
9
+
10
+ def gem(*args)
11
+ world.gem @name, *args
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require "tmpdir"
2
+ require "envandle/version"
3
+ require "envandle/as_reference"
4
+ require "envandle/as_git_reference"
5
+ require "envandle/bundle_dsl"
6
+ require "envandle/gem"
7
+ require "envandle/gemfile"
8
+ require "envandle/gemspec"
9
+ require "envandle/git"
10
+ require "envandle/git_branch_reference"
11
+ require "envandle/group_dsl"
12
+ require "envandle/path_reference"
13
+ require "envandle/shell"
14
+ require "envandle/reference_cache"
@@ -0,0 +1,19 @@
1
+ module Envandle
2
+ class PathReference
3
+ extend AsReference
4
+
5
+ def initialize(group, name, path)
6
+ @group = group
7
+ @name = name
8
+ @path = path
9
+ end
10
+
11
+ def to_gem(args, options)
12
+ Gem.new(@group, @name, [], {path: @path})
13
+ end
14
+
15
+ def spec
16
+ @spec ||= Gemspec.new(Gemspec.find_file(@path, name: @name))
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,69 @@
1
+ module Envandle
2
+ class ReferenceCache
3
+ def self.key(group, name)
4
+ if group
5
+ "#{name}@#{group}"
6
+ else
7
+ name
8
+ end
9
+ end
10
+
11
+ def find(key, name)
12
+ paths[key] ||
13
+ git_branches[key] ||
14
+ paths[name] ||
15
+ git_branches[name]
16
+ end
17
+
18
+ def paths
19
+ @paths ||= parse(:path, PathReference, "ENVANDLE_GEM_PATH")
20
+ end
21
+
22
+ def git_branches
23
+ @git_branches ||= parse(:git, GitBranchReference, "ENVANDLE_GEM_GIT_BRANCH")
24
+ end
25
+
26
+ def parse(key, klass, env)
27
+ {}.tap do |h|
28
+ (ENV[env].to_s).split(";").each do |i|
29
+ if v = __send__("parse_#{key}", klass, env, i)
30
+ h[v.key] = v if v
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def parse_group_and_name(env, v)
37
+ name, group = v.to_s.strip.split("@")
38
+ name = name.to_s.strip
39
+ group = group.to_s.strip if group
40
+ raise "No gem name (#{env}): #{ENV[env]}" if name.empty?
41
+ raise "No group name (#{env}): #{ENV[env]}" if group && group.empty?
42
+ [group, name]
43
+ end
44
+
45
+ def parse_path(klass, env, v)
46
+ v = v.to_s.strip
47
+ return if v.empty?
48
+ a = v.split(":")
49
+ name = a[0].to_s.strip
50
+ path = a[1..-1].join(":").to_s.strip
51
+ raise "No gem path (#{env}): #{ENV[env]}" if path.empty?
52
+ klass.new(*parse_group_and_name(env, name), path)
53
+ end
54
+
55
+ def parse_git(klass, env, v)
56
+ v = v.to_s.strip
57
+ return if v.empty?
58
+ a = v.split(":")
59
+ name = a[0].to_s.strip
60
+ path = a[1..-1].join(":").to_s.strip
61
+ url_and_ref = path.split('#')
62
+ url = url_and_ref[0].to_s.strip
63
+ ref = url_and_ref[1].to_s.strip
64
+ raise "No gem git url (#{env}): #{ENV[env]}" if url.empty?
65
+ raise "No gem git ref/branch/tag (#{env}): #{ENV[env]}" if ref.empty?
66
+ klass.new(*parse_group_and_name(env, name), url, ref)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,6 @@
1
+ module Envandle
2
+ def self.sh(cmd)
3
+ system cmd, out: "/dev/null", err: "/dev/null"
4
+ raise "Command error: #{cmd}" unless $?.success?
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Envandle
2
+ VERSION = "0.1.0"
3
+ end
data/lib/envandle.rb ADDED
@@ -0,0 +1 @@
1
+ require "envandle/binding"
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: envandle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - mosop
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-01-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ description:
56
+ email:
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".gitignore"
62
+ - ".rspec"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - README.md
66
+ - Rakefile
67
+ - bin/console
68
+ - bin/setup
69
+ - envandle.gemspec
70
+ - lib/envandle.rb
71
+ - lib/envandle/as_git_reference.rb
72
+ - lib/envandle/as_reference.rb
73
+ - lib/envandle/binding.rb
74
+ - lib/envandle/bundle_dsl.rb
75
+ - lib/envandle/gem.rb
76
+ - lib/envandle/gemfile.rb
77
+ - lib/envandle/gemspec.rb
78
+ - lib/envandle/git.rb
79
+ - lib/envandle/git_branch_reference.rb
80
+ - lib/envandle/group_dsl.rb
81
+ - lib/envandle/lib.rb
82
+ - lib/envandle/path_reference.rb
83
+ - lib/envandle/reference_cache.rb
84
+ - lib/envandle/shell.rb
85
+ - lib/envandle/version.rb
86
+ homepage: https://github.com/mosop/envandle
87
+ licenses: []
88
+ metadata:
89
+ allowed_push_host: https://rubygems.org
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.5.1
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: A library for enabling Gemfiles to specify gem locations from environment
110
+ variables.
111
+ test_files: []