ecogem 0.0.1
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 +7 -0
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +143 -0
- data/Rakefile +2 -0
- data/bin/ecogem +6 -0
- data/ecogem.gemspec +23 -0
- data/lib/ecogem.rb +36 -0
- data/lib/ecogem/cli.rb +21 -0
- data/lib/ecogem/cli/args.rb +35 -0
- data/lib/ecogem/cli/commands/install.rb +22 -0
- data/lib/ecogem/cli/commands/update.rb +22 -0
- data/lib/ecogem/config.rb +11 -0
- data/lib/ecogem/config/entries.rb +10 -0
- data/lib/ecogem/config/entries/git_sources.rb +11 -0
- data/lib/ecogem/config/git_source.rb +17 -0
- data/lib/ecogem/env.rb +34 -0
- data/lib/ecogem/gemfile.rb +95 -0
- data/lib/ecogem/gemfile/dependency.rb +64 -0
- data/lib/ecogem/gemfile/marshal.rb +35 -0
- data/lib/ecogem/gemfile/source.rb +58 -0
- data/lib/ecogem/git.rb +56 -0
- data/lib/ecogem/gitsfile.rb +19 -0
- data/lib/ecogem/gitsfile/entries.rb +10 -0
- data/lib/ecogem/gitsfile/entries/keys.rb +15 -0
- data/lib/ecogem/util.rb +8 -0
- data/lib/ecogem/util/config.rb +62 -0
- data/lib/ecogem/util/config/entry.rb +19 -0
- data/lib/ecogem/util/config/value.rb +8 -0
- data/lib/ecogem/util/config/value_container.rb +86 -0
- data/lib/ecogem/version.rb +3 -0
- data/lib/ecogem/workspace.rb +65 -0
- metadata +105 -0
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
data/Gemfile
ADDED
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
data/bin/ecogem
ADDED
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
|
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
|
data/lib/ecogem/util.rb
ADDED
@@ -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,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,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: []
|