ecogem 0.0.1

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: 60fc0a280bf16df9aa4c75207a8ab7932f30fc82
4
+ data.tar.gz: 4bd3bd7d9bbc67fd304fab346b9a673250e3029d
5
+ SHA512:
6
+ metadata.gz: b48b9f03002c2e445cce5f3130548a49f3253b532597f93437d05b3549fd4e77d16db8b17d68b050249aca1ff6b4875c9f1ac94f126ff4ae2efd83976a1971b5
7
+ data.tar.gz: b8da5d7c670404b81c4bf107ff78a8ee9be4b7a1051eab7003b6be90dac01e6e79e03a794a43b549a75ddfa5b75a222824b682259a4a94019ef452bfb782e8f3
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ /.ruby-version
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rbmary.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 mosop
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # Ecogem
2
+
3
+ Supplements Bundler for installing private gems.
4
+
5
+ ## Preface
6
+
7
+ When the gem A depends on my private gem B whose source is served from GitHub, I can write Gemfile with _:git_ option.
8
+
9
+ A's Gemfile:
10
+
11
+ ```ruby
12
+ source 'https://rubygems.org'
13
+ gem 'gem-b', git: 'git@github.com:me/gem-b.git'
14
+ gemspec
15
+ ```
16
+
17
+ It's cool. So, I also want to privately put A's source onto GitHub and use A in my application.
18
+
19
+ My application's Gemfile:
20
+
21
+ ```ruby
22
+ source 'https://rubygems.org'
23
+ gem 'gem-a', git: 'git@github.com:me/gem-a.git'
24
+ ```
25
+
26
+ Then `bundle install` prints:
27
+
28
+ Could not find gem 'gem-b (>= 0) ruby', which is required by gem 'gem-a (>= 0) ruby', in any of the sources.
29
+
30
+ Oh, my! Bundler does not resolve such deep dependencies.
31
+
32
+ To solve this, I need to:
33
+
34
+ * add the dependency again like:
35
+
36
+ ```ruby
37
+ gem 'gem-a', git: 'git@github.com:me/gem-a.git'
38
+ gem 'gem-b', git: 'git@github.com:me/gem-b.git'
39
+ ```
40
+
41
+ It's terrible. Where is DRY?
42
+
43
+ * host my private Gem server
44
+
45
+ The regular Gem server protocol is not suitable to exchange private resources because it has no sophisticated authentication method such as SSH.
46
+
47
+ * subscribe to Gemfury
48
+
49
+ Better than self hosting, however, there is still the problem about authentication.
50
+
51
+ * make Rubygems accept Git sources
52
+
53
+ * make Bundler resolve nested Git dependencies
54
+
55
+ These two seem to take forever.
56
+
57
+ Okay. The last option is Ecogem.
58
+
59
+ ## Dependencies
60
+
61
+ * fork(2) and UNIX domain socket
62
+ * Windows and several other platforms are not supported.
63
+
64
+ * Ruby >= 2.1 and ~> 2.2
65
+ * Tested on 2.1.5 (MRI)
66
+
67
+ * Bundler >= 1.7.9
68
+ * Tested on 1.7.9
69
+
70
+ ## Installation
71
+
72
+ Install the gem:
73
+
74
+ $ gem install ecogem
75
+
76
+ Also install Bundler if not installed:
77
+
78
+ $ gem install bundler
79
+
80
+ ## Usage
81
+
82
+ Rename your Gemfile to Ecogemfile and execute:
83
+
84
+ $ ecogem install
85
+
86
+ ## Example
87
+
88
+ When
89
+
90
+ * My application depends on gem-a whose source is served from GitHub
91
+ * gem-a depends on gem-b whose source is served from GitHub
92
+
93
+ Then `ecogem install` will:
94
+
95
+ 1. parse Ecogemfile
96
+
97
+ Ecogemfile:
98
+
99
+ ```ruby
100
+ source 'https://rubygems.org'
101
+ gem 'gem-a', git: 'git@github.com:me/gem-a.git'
102
+ gem 'rake' # from rubygems.org
103
+ ```
104
+
105
+ 1. fetch gem-a's Gemfile
106
+
107
+ gem-a's Gemfile:
108
+
109
+ ```ruby
110
+ source 'https://rubygems.org'
111
+ gem 'gem-b', git: 'git@github.com:me/gem-b.git'
112
+ gemspec
113
+ ```
114
+
115
+ 1. fetch gem-b's Gemfile
116
+
117
+ gem-b's Gemfile:
118
+
119
+ ```ruby
120
+ source 'https://rubygems.org'
121
+ gemspec
122
+ ```
123
+
124
+ 1. create a new Gemfile file
125
+
126
+ Gemfile:
127
+
128
+ ```ruby
129
+ source 'https://rubygems.org'
130
+ gem 'gem-b', '>= 0', git: 'git@github.com:me/gem-b.git', branch: 'master'
131
+ gem 'gem-a', '>= 0', git: 'git@github.com:me/gem-a.git', branch: 'master'
132
+ gem 'rake', '>= 0'
133
+ ```
134
+
135
+ 1. and finally execute `bundle install` with the new Gemfile
136
+
137
+ ## Contributing
138
+
139
+ 1. Fork it ( https://github.com/[my-github-username]/ecogem/fork )
140
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
141
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
142
+ 4. Push to the branch (`git push origin my-new-feature`)
143
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/ecogem ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'ecogem'
4
+
5
+ Ecogem::Cli.start(ARGV)
6
+
data/ecogem.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ecogem/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ecogem"
8
+ spec.version = Ecogem::VERSION
9
+ spec.authors = ["mosop"]
10
+ spec.email = [""]
11
+ spec.summary = %q{Supplements Bundler for installing private gems.}
12
+ spec.description = %q{}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
data/lib/ecogem.rb ADDED
@@ -0,0 +1,36 @@
1
+ require_relative 'ecogem/version'
2
+
3
+ Object.autoload :Bundler, 'bundler' unless Object.const_defined?(:Bundler, false)
4
+
5
+ module Ecogem
6
+ %w[cli config env gemfile git gitsfile util workspace].each do |name|
7
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
8
+ autoload pascal, ::File.expand_path("../ecogem/#{name}", __FILE__)
9
+ end
10
+
11
+ def self.workspaces
12
+ ::Thread.current[:ecogem_workspaces] ||= []
13
+ end
14
+
15
+ def self.workspace
16
+ workspaces.last
17
+ end
18
+
19
+ def self.new_workspace(args, options = {}, &block)
20
+ Workspace.new(args, options) do |ws|
21
+ begin
22
+ ::Thread.current[:ecogem_workspaces] ||= []
23
+ workspaces << ws
24
+ break block.call(ws)
25
+ ensure
26
+ workspaces.pop
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.git_path(key)
32
+ new_workspace(nil, readonly: true) do |ws|
33
+ break ws.gitsfile.dir_of(key)
34
+ end
35
+ end
36
+ end
data/lib/ecogem/cli.rb ADDED
@@ -0,0 +1,21 @@
1
+ require_relative 'cli/args'
2
+
3
+ module Ecogem
4
+ class Cli
5
+ def self.start(argv)
6
+ self.new(argv).execute
7
+ end
8
+
9
+ def initialize(argv)
10
+ @args = ::Ecogem::Cli::Args.new(argv)
11
+ end
12
+
13
+ def execute
14
+ raise "Unknown command: #{@args.command}" unless %w[install update].include?(@args.command)
15
+ require_relative "cli/commands/#{@args.command}"
16
+ klass_name = @args.command.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
17
+ klass = ::Ecogem::Cli::Commands.const_get(klass_name, false)
18
+ klass.new(@args).execute
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ module Ecogem
2
+ class Cli
3
+ class Args
4
+ attr_reader :command
5
+
6
+ def initialize(argv)
7
+ @argv = argv.dup
8
+ parse
9
+ end
10
+
11
+ def options
12
+ @options ||= {}
13
+ end
14
+
15
+ def bundler_args
16
+ @argv
17
+ end
18
+
19
+ private def parse
20
+ @command = @argv.shift
21
+ extract_options
22
+ @argv.freeze
23
+ end
24
+
25
+ private def extract_options
26
+ %i[file port].each do |key|
27
+ if found = @argv.find_index("--ecogem-#{key}")
28
+ name, value = @argv.slice(found, 2)
29
+ options[key] = value
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+
3
+ module Ecogem
4
+ class Cli
5
+ module Commands
6
+ class Install
7
+ def initialize(args)
8
+ @args = args
9
+ end
10
+
11
+ def execute
12
+ ::Ecogem.new_workspace(@args) do |ws|
13
+ gemfile = "--gemfile=#{ws.gemfile.write.inspect}"
14
+ args = [*@args.bundler_args, gemfile].join(' ')
15
+ command = "bundle install #{args}"
16
+ system command
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+
3
+ module Ecogem
4
+ class Cli
5
+ module Commands
6
+ class Update
7
+ def initialize(args)
8
+ @args = args
9
+ end
10
+
11
+ def execute
12
+ ::Ecogem.new_workspace(@args) do |ws|
13
+ gemfile = "--gemfile=#{ws.gemfile.write.inspect}"
14
+ args = [*@args.bundler_args, gemfile].join(' ')
15
+ command = "bundle update #{args}"
16
+ system command
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module Ecogem
2
+ class Config < ::Ecogem::Util::Config
3
+ %w[entries git_source].each do |name|
4
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
5
+ autoload pascal, ::File.expand_path("../config/#{name}", __FILE__)
6
+ end
7
+
8
+ entry_namespace Entries
9
+ entry :git_sources
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Ecogem
2
+ class Config
3
+ module Entries
4
+ %w[git_sources].each do |name|
5
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
6
+ autoload pascal, ::File.expand_path("../entries/#{name}", __FILE__)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Ecogem
2
+ class Config
3
+ module Entries
4
+ class GitSources < ::Ecogem::Util::Config::Entry
5
+ def parse(data)
6
+ (data || []).map{|i| ::Ecogem::Config::GitSource.new(i)}
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module Ecogem
2
+ class Config
3
+ class GitSource
4
+ def initialize(data)
5
+ @data = data
6
+ end
7
+
8
+ def uri
9
+ @data['uri']
10
+ end
11
+
12
+ def uri_alias
13
+ @data['uri_alias']
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/ecogem/env.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'yaml'
2
+
3
+ module Ecogem
4
+ class Env
5
+ %w[git_source].each do |name|
6
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
7
+ autoload pascal, ::File.expand_path("../env/#{name}", __FILE__)
8
+ end
9
+
10
+ attr_reader :dir
11
+
12
+ def initialize(base, dir)
13
+ @base = base
14
+ @dir = ::File.expand_path(dir)
15
+ end
16
+
17
+ private def config_path
18
+ @config_path ||= "#{dir}/config"
19
+ end
20
+
21
+ def config
22
+ @config ||= ::Ecogem::Config.new(@base && @base.config, config_path)
23
+ end
24
+
25
+ def git_sources
26
+ @git_sources ||= ::Hash[config.values.git_sources.map{|i| [i.uri, i]}]
27
+ end
28
+
29
+ def git_source_uri_to_alias(uri)
30
+ source = git_sources[uri]
31
+ (source && source.uri_alias) || uri
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,95 @@
1
+ module Ecogem
2
+ class Gemfile
3
+ %w[dependency marshal source].each do |name|
4
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
5
+ autoload pascal, ::File.expand_path("../gemfile/#{name}", __FILE__)
6
+ end
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def dir
13
+ @dir ||= ::File.dirname(@pah)
14
+ end
15
+
16
+ private def dependencies
17
+ @dependencies ||= data.dependencies.map{|i| ::Ecogem::Gemfile::Dependency.new(self, i)}
18
+ end
19
+
20
+ private def extracted_dependencies
21
+ @extracted_dependencies ||= extract_dependencies([], [], false)
22
+ end
23
+
24
+ protected def extract_dependencies(into, gits, git_only)
25
+ dependencies.each do |d|
26
+ if d.source.git?
27
+ unless gits.include?(d.source.git.key)
28
+ gits << d.source.git.key
29
+ d.source.git.gemfile.extract_dependencies into, gits, true if d.source.git.gemfile
30
+ end
31
+ into << d
32
+ else
33
+ into << d unless git_only
34
+ end
35
+ end
36
+ into
37
+ end
38
+
39
+ private def sources
40
+ @sources ||= data.sources.instance_variable_get(:@rubygems_aggregate).remotes.map{|i| i.to_s}
41
+ end
42
+
43
+ def code
44
+ @code ||= begin
45
+ a = []
46
+ a << 'require "ecogem"'
47
+ a << sources.reverse.map{|i| "source #{i.inspect}"}.join("\n")
48
+ a << extracted_dependencies.map{|i| i.code}.uniq.join("\n")
49
+ a.join("\n\n")
50
+ end
51
+ end
52
+
53
+ def write(dir = nil, name = nil)
54
+ dir ||= ::File.dirname(@path)
55
+ name ||= 'Gemfile'
56
+ path = "#{dir}/#{name}"
57
+ ::File.write "#{dir}/#{name}", code
58
+ path
59
+ end
60
+
61
+ private def data
62
+ @data ||= load
63
+ end
64
+
65
+ private def load
66
+ in_r, in_w, out_r, out_w = []
67
+
68
+ begin
69
+ in_r, in_w = ::IO.pipe
70
+ out_r, out_w = ::IO.pipe
71
+
72
+ params = {
73
+ path: @path
74
+ }
75
+ ::Marshal.dump({path: @path}, in_w)
76
+
77
+ pid = ::Process.fork do
78
+ params = ::Marshal.load(in_r)
79
+
80
+ dsl = ::Bundler::Dsl.new
81
+ dsl.eval_gemfile(params[:path])
82
+ result = ::Ecogem::Gemfile::Marshal.new(dsl).to_data
83
+
84
+ ::Marshal.dump(result, out_w)
85
+ ::Process.exit!
86
+ end
87
+ ::Process.waitpid(pid)
88
+
89
+ ::Marshal.load(out_r)
90
+ ensure
91
+ [in_r, in_w, out_r, out_w].each{|i| i.close if i}
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,64 @@
1
+ module Ecogem
2
+ class Gemfile
3
+ class Dependency
4
+ def initialize(gemfile, data)
5
+ @gemfile = gemfile
6
+ @data = data
7
+ end
8
+
9
+ def name
10
+ @data.name
11
+ end
12
+
13
+ def source
14
+ @source ||= ::Ecogem::Gemfile::Source.new(self, @data.instance_variable_get(:@source))
15
+ end
16
+
17
+ def versions
18
+ @versions ||= @data.requirement.requirements.map{|i| "#{i[0]} #{i[1]}"}
19
+ end
20
+
21
+ def platforms
22
+ @platforms ||= @data.instance_variable_get(:@platforms).dup
23
+ end
24
+
25
+ def groups
26
+ @groups ||= @data.instance_variable_get(:@groups).dup
27
+ end
28
+
29
+ def code
30
+ @code ||= begin
31
+ a = ["gem \"#{name}\""]
32
+
33
+ if !(versions.size == 1 && versions[0] == '>= 0')
34
+ a << versions.map{|i| "\"#{i}\""}.join(', ')
35
+ end
36
+
37
+ if platforms.size > 0
38
+ s = if platforms.size == 1
39
+ ":#{platforms[0]}"
40
+ else
41
+ '[' + platforms.map{|i| ":#{i}"}.join(', ') + ']'
42
+ end
43
+ a << "platform: #{s}"
44
+ end
45
+
46
+ if groups.size > 0 && !(groups.size == 1 && groups[0] == :default)
47
+ s = if groups.size == 1
48
+ ":#{groups[0]}"
49
+ else
50
+ '[' + groups.map{|i| ":#{i}"}.join(', ') + ']'
51
+ end
52
+ a << "group: #{s}"
53
+ end
54
+
55
+ if s = source.code
56
+ a << s
57
+ end
58
+
59
+ a.join(', ')
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,35 @@
1
+ module Ecogem
2
+ class Gemfile
3
+ class Marshal
4
+ def initialize(dsl)
5
+ @dsl = dsl
6
+ end
7
+
8
+ def to_data
9
+ h = {
10
+ dependencies: @dsl.dependencies,
11
+ sources: @dsl.instance_variable_get(:@sources)
12
+ }
13
+ Data.new(h)
14
+ end
15
+
16
+ class Data
17
+ def initialize(hash)
18
+ @hash = hash
19
+ end
20
+
21
+ def dependencies
22
+ @hash[:dependencies]
23
+ end
24
+
25
+ def groups
26
+ @hash[:groups]
27
+ end
28
+
29
+ def sources
30
+ @hash[:sources]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ require 'fileutils'
2
+
3
+ module Ecogem
4
+ class Gemfile
5
+ class Source
6
+ attr_reader :git
7
+
8
+ def initialize(dependency, data)
9
+ @dependency = dependency
10
+ @data = data
11
+ end
12
+
13
+ def git?
14
+ @data && @data.options.key?('git')
15
+ end
16
+
17
+ def path?
18
+ @data && @data.options.key?('path')
19
+ end
20
+
21
+ def source?
22
+ @data && @data.options.key?('remotes')
23
+ end
24
+
25
+ def git_uri
26
+ @data.options['git']
27
+ end
28
+
29
+ def path
30
+ @data.options['path']
31
+ end
32
+
33
+ def source
34
+ @data.options['remotes'][0]
35
+ end
36
+
37
+ def ref
38
+ @data.ref
39
+ end
40
+
41
+ def git
42
+ @git ||= ::Ecogem::Git.new(git_uri, ref)
43
+ end
44
+
45
+ def code
46
+ @code ||= begin
47
+ if git?
48
+ "path: Ecogem.git_path(#{git.key.inspect})"
49
+ elsif path?
50
+ "path: #{path.to_s.inspect}"
51
+ elsif source?
52
+ "source: #{source.inspect}"
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/ecogem/git.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'fileutils'
2
+
3
+ module Ecogem
4
+ class Git
5
+ def initialize(uri, ref)
6
+ @uri = uri
7
+ @ref = ref || 'master'
8
+ end
9
+
10
+ def key
11
+ @key ||= "#{@uri} #{@ref}"
12
+ end
13
+
14
+ def dir
15
+ @dir ||= ::Ecogem.workspace.gitsfile.dir_of(key)
16
+ end
17
+
18
+ def uri_alias
19
+ @uri_alias ||= ::Ecogem.workspace.env.git_source_uri_to_alias(@uri)
20
+ end
21
+
22
+ def exec(cmd)
23
+ puts "git: #{cmd}"
24
+ cmd = "git #{cmd}"
25
+ system("cd \"#{dir}\"; #{cmd}")
26
+ end
27
+
28
+ private def load
29
+ unless @loaded
30
+ ::FileUtils.rm_rf dir
31
+ ::FileUtils.mkdir_p dir
32
+ self.exec "init -q"
33
+ self.exec "remote add origin \"#{uri_alias}\""
34
+ self.exec "fetch -q origin #{@ref}"
35
+ raise CommandError unless $?.success?
36
+ self.exec "checkout -q FETCH_HEAD"
37
+ raise CommandError unless $?.success?
38
+ @loaded = true
39
+ end
40
+ end
41
+
42
+ private def gemfile_path
43
+ @gemfile_path ||= ::File.expand_path("#{dir}/Ecogemfile")
44
+ end
45
+
46
+ def gemfile
47
+ @gemfile ||= begin
48
+ load
49
+ ::Ecogem::Gemfile.new(gemfile_path) if ::File.file?(gemfile_path)
50
+ end
51
+ end
52
+
53
+ class CommandError < ::StandardError
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ module Ecogem
2
+ class Gitsfile < ::Ecogem::Util::Config
3
+ %w[entries].each do |name|
4
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
5
+ autoload pascal, ::File.expand_path("../gitsfile/#{name}", __FILE__)
6
+ end
7
+
8
+ entry_namespace Entries
9
+ entry :keys
10
+
11
+ def dir_of(key)
12
+ i = values.keys.find_index(key) || begin
13
+ values.keys << key
14
+ values.keys.size - 1
15
+ end
16
+ "#{dir}/#{i+1}"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module Ecogem
2
+ class Gitsfile
3
+ module Entries
4
+ %w[keys].each do |name|
5
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
6
+ autoload pascal, ::File.expand_path("../entries/#{name}", __FILE__)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module Ecogem
2
+ class Gitsfile
3
+ module Entries
4
+ class Keys < ::Ecogem::Util::Config::Entry
5
+ def parse(data)
6
+ (data || []).dup
7
+ end
8
+
9
+ def unparse(value)
10
+ value.dup
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ module Ecogem
2
+ module Util
3
+ %w[config].each do |name|
4
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
5
+ autoload pascal, ::File.expand_path("../util/#{name}", __FILE__)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,62 @@
1
+ require 'yaml'
2
+
3
+ module Ecogem
4
+ module Util
5
+ class Config
6
+ %w[entry value value_container].each do |name|
7
+ pascal = name.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
8
+ autoload pascal, ::File.expand_path("../config/#{name}", __FILE__)
9
+ end
10
+
11
+ def self.entry_namespaces
12
+ @entry_namespaces ||= []
13
+ end
14
+
15
+ def self.entry_namespace(ns)
16
+ entry_namespaces << ns
17
+ end
18
+
19
+ def self.entry(key)
20
+ e = ::Ecogem::Util::Config::Entry.create(self, key)
21
+ entries[key] = e
22
+ end
23
+
24
+ def self.find_entry_class(key)
25
+ pascal = key.to_s.split(/_/).map{|i| i[0].upcase + i[1..-1]}.join('')
26
+ entry_namespaces.reverse.each do |ns|
27
+ return ns.const_get(pascal, false) if ns.const_defined?(pascal, false)
28
+ end
29
+ nil
30
+ end
31
+
32
+ def self.entries
33
+ @entries ||= {}
34
+ end
35
+
36
+ def initialize(base, path)
37
+ @base = base
38
+ @path = ::File.expand_path(path)
39
+ end
40
+
41
+ def dir
42
+ @dir ||= ::File.dirname(@path)
43
+ end
44
+
45
+ protected def value_container
46
+ @value_conatiner ||= ::Ecogem::Util::Config::ValueContainer.new(@base && @base.value_container, self, load || {})
47
+ end
48
+
49
+ def values
50
+ @values ||= value_container.proxy
51
+ end
52
+
53
+ private def load
54
+ ::YAML.load(::File.read(@path)) if ::File.file?(@path)
55
+ end
56
+
57
+ def save
58
+ ::File.write @path, value_container.values_to_h.to_yaml
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,19 @@
1
+ module Ecogem
2
+ module Util
3
+ class Config
4
+ class Entry
5
+ attr_reader :key
6
+
7
+ def initialize(config, key)
8
+ @config = config
9
+ @key = key
10
+ end
11
+
12
+ def self.create(config, key, options = {})
13
+ klass = options[:class] || config.find_entry_class(key)
14
+ klass.new(config, key)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ module Ecogem
2
+ module Util
3
+ class Config
4
+ class Value
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,86 @@
1
+ module Ecogem
2
+ module Util
3
+ class Config
4
+ class ValueContainer
5
+ def initialize(base, config, default_data)
6
+ @base = base
7
+ @config = config
8
+ @default_data = default_data
9
+ end
10
+
11
+ def proxy
12
+ @proxy ||= Proxy.new(self)
13
+ end
14
+
15
+ def values
16
+ @values ||= h_to_values(@default_data || {})
17
+ end
18
+
19
+ def h_to_values(h)
20
+ values = {}
21
+ h.each do |k, v|
22
+ k = k.to_sym
23
+ entry = @config.class.entries[k]
24
+ values[k] = entry.parse(v) if entry
25
+ end
26
+ values
27
+ end
28
+
29
+ def values_to_h
30
+ h = {}
31
+ values.each do |k, v|
32
+ entry = @config.class.entries[k]
33
+ h[k.to_s] = entry.unparse(v)
34
+ end
35
+ h
36
+ end
37
+
38
+ def resolve_method(name, *args, &block)
39
+ key = name.to_s.sub(/(=)$/, '').to_sym
40
+ assign = $1
41
+ entry = @config.class.entries[key]
42
+ if entry
43
+ if assign
44
+ return values[key] = args.first
45
+ else
46
+ begin
47
+ return find_value(key)
48
+ rescue NotFoundError
49
+ value = entry.parse(nil)
50
+ values[key] = value
51
+ return value
52
+ end
53
+ end
54
+ end
55
+ raise UnresolvedError
56
+ end
57
+
58
+ def find_value(key)
59
+ return values[key] if values.key?(key)
60
+ return @base.find_value(key) if @base
61
+ raise NotFoundError
62
+ end
63
+
64
+ class NotFoundError < ::StandardError
65
+ end
66
+
67
+ class UnresolvedError < ::StandardError
68
+ end
69
+
70
+ class Proxy
71
+ def initialize(container)
72
+ @container = container
73
+ end
74
+
75
+ def method_missing(name, *args, &block)
76
+ begin
77
+ return @container.resolve_method(name, *args, &block)
78
+ rescue ::Ecogem::Util::Config::ValueContainer::UnresolvedError
79
+ end
80
+ super
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,3 @@
1
+ module Ecogem
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,65 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+ require 'yaml'
4
+
5
+ module Ecogem
6
+ class Workspace
7
+ def initialize(args, options = {}, &block)
8
+ @args = args || ::Ecogem::Cli::Args.new([])
9
+ options = {}.merge(options)
10
+ new_tmpdir do |dir|
11
+ begin
12
+ @workdir = dir
13
+ block.call self
14
+ unless options[:readonly]
15
+ gitsfile.save
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ def global_env
22
+ @global_env ||= ::Ecogem::Env.new(nil, ::File.expand_path(::Dir.home + '/.ecogem'))
23
+ end
24
+
25
+ def env
26
+ @env ||= ::Ecogem::Env.new(global_env, env_path)
27
+ end
28
+
29
+ def gitsfile
30
+ @gitsfile ||= ::Ecogem::Gitsfile.new(nil, global_env.dir + '/gits/keys')
31
+ end
32
+
33
+ private def env_path
34
+ @env_path ||= begin
35
+ path = ::File.expand_path(@args.options[:env] || ::File.dirname(gemfile_path) + '/.ecogem')
36
+ raise "file exists: #{path}" if ::File.file?(path)
37
+ ::FileUtils.mkdir_p path unless ::File.exist?(path)
38
+ path
39
+ end
40
+ end
41
+
42
+ private def gemfile_path
43
+ @gemfile_path ||= ::File.expand_path(@args.options[:gemfile] || ::Dir.pwd + '/Ecogemfile')
44
+ end
45
+
46
+ def gemfile
47
+ @gemfile ||= ::Ecogem::Gemfile.new(gemfile_path)
48
+ end
49
+
50
+ private def tmp_path
51
+ @tmp_path ||= begin
52
+ path = File.expand_path(@args.options[:tmpdir] || "#{env_path}/tmp")
53
+ raise "file exists: #{path}" if ::File.file?(path)
54
+ path
55
+ end
56
+ end
57
+
58
+ def new_tmpdir(&block)
59
+ ::FileUtils.mkdir_p tmp_path unless ::File.exist?(tmp_path)
60
+ ::Dir.mktmpdir(nil, tmp_path) do |dir|
61
+ return block.call(dir)
62
+ end
63
+ end
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ecogem
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - mosop
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-12 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
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
+ description: ''
42
+ email:
43
+ - ''
44
+ executables:
45
+ - ecogem
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/ecogem
55
+ - ecogem.gemspec
56
+ - lib/ecogem.rb
57
+ - lib/ecogem/cli.rb
58
+ - lib/ecogem/cli/args.rb
59
+ - lib/ecogem/cli/commands/install.rb
60
+ - lib/ecogem/cli/commands/update.rb
61
+ - lib/ecogem/config.rb
62
+ - lib/ecogem/config/entries.rb
63
+ - lib/ecogem/config/entries/git_sources.rb
64
+ - lib/ecogem/config/git_source.rb
65
+ - lib/ecogem/env.rb
66
+ - lib/ecogem/gemfile.rb
67
+ - lib/ecogem/gemfile/dependency.rb
68
+ - lib/ecogem/gemfile/marshal.rb
69
+ - lib/ecogem/gemfile/source.rb
70
+ - lib/ecogem/git.rb
71
+ - lib/ecogem/gitsfile.rb
72
+ - lib/ecogem/gitsfile/entries.rb
73
+ - lib/ecogem/gitsfile/entries/keys.rb
74
+ - lib/ecogem/util.rb
75
+ - lib/ecogem/util/config.rb
76
+ - lib/ecogem/util/config/entry.rb
77
+ - lib/ecogem/util/config/value.rb
78
+ - lib/ecogem/util/config/value_container.rb
79
+ - lib/ecogem/version.rb
80
+ - lib/ecogem/workspace.rb
81
+ homepage: ''
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.2.2
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Supplements Bundler for installing private gems.
105
+ test_files: []