gemtronics 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009 markbates
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,118 @@
1
+ =Gemtronics - Simple and Smart Gem Management
2
+
3
+ Gemtronics is designed to mitigate the pain of gem management for your Ruby applications. It can be used with standalone Ruby libraries or in Rails applications, it doesn't much matter to Gemtronics.
4
+
5
+ ===Installation
6
+
7
+ Gemtronics is, itself, a RubyGem. So yes, there is on dependency you have to have on your machine before you can use it to manage your other gems for your projects.
8
+
9
+ $ sudo gem install gemtronics
10
+
11
+ Or, if you prefer to live on the edge:
12
+
13
+ $ sudo gem install markbates-gemtronics --source=http://gems.github.com
14
+
15
+ ==Usage
16
+
17
+ Gemtronics comes bundled with a binary that can help make life a little nicer. The binary has three different options, generate, convert, and install.
18
+
19
+ ===Generate
20
+
21
+ Gemtronics will generate a sample file for you by using the binary, like such:
22
+
23
+ $ gemtronics generate
24
+
25
+ That will output the following into a file called <code>config/gemtronics.rb</code>:
26
+
27
+ group(:default) do |g|
28
+ # g.add('gem name here')
29
+ # g.add('gem name here', :version => '1.2.3')
30
+ # g.add('gem name here', :version => '1.2.3', :source => 'http://gems.example.com')
31
+ # g.add('gem name here', :version => '1.2.3', :source => 'http://gems.example.com', :require => ['file1', 'file2'])
32
+ end
33
+
34
+ group(:production, :dependencies => :default) do |g|
35
+ end
36
+
37
+ group(:development, :dependencies => :default) do |g|
38
+ end
39
+
40
+ group(:test, :dependencies => :development) do |g|
41
+ end
42
+
43
+ If you don't like that file path you can tell it where to generate the file for you:
44
+
45
+ $ gemtronics generate path/to/my/file.rb
46
+
47
+ It is encouraged that you use the default path for your file, as it will make it easier for Gemtronics to find it later.
48
+
49
+ ===Convert
50
+
51
+ On the off chance you are using the old Gemtools project for managing your gems, Gemtronics can easily convert that old school YAML file to the Gemtronics format:
52
+
53
+ $ gemtronics convert path/to/my/gems.yml
54
+
55
+ ===Install
56
+
57
+ Once you have setup your Gemtronics file, more on that in a minute, you can use it to easily install your gems from it:
58
+
59
+ $ gemtronics install
60
+
61
+ Gemtronics will read the <code>config/gemtronics.rb</code> and install all the gems in the <code>:default</code> group. If you would like to specify a different group you can do that like so:
62
+
63
+ $ gemtronics install production
64
+
65
+ If you did not put your file in <code>config/gemtronics.rb</code> you will need to specify the path:
66
+
67
+ $ gemtronics install default path/to/my/file.rb
68
+
69
+ Gemtronics will not install gems again if they already exist on your machine. This makes installation fast and easy!
70
+
71
+ ==Configuring Your Gems
72
+
73
+ Gemtronics has the concept that gems can be grouped. Why would you want to group your gems? Great question. Perhaps you have a default set of gems that you want to use with your application, you would put them in the <code>default</code> group. In testing and development you might want to include other gems, such as <code>ruby-debug</code>, that you wouldn't want running/installed on your production machines. In this case you would group them in another group that depends on the <code>default</code> group.
74
+
75
+ Defining a group is very easy:
76
+
77
+ group(:default) do |g|
78
+ g.add('gem1')
79
+ end
80
+
81
+ When you add gems to a group you can set all the necessary gem options, or just inherit the default options. See the sample file below, or the rest of the RDOC for more information.
82
+
83
+ ===Rails
84
+
85
+ Right about now you're saying to yourself, I use the Rails gem management system, why should I use this? Well, because the Rails gem management system is flawed at it's very core. You define your gems in the environment, which means the environment must be loaded to load/install your gems. However, this cause blow up if a gem is not installed when it loads the environment. Plus, why would you want to load the environment just to install gems?
86
+
87
+ Gemtronics also has the advantage of being an independent system to Rails, which means that you can use it to install Rails for you!
88
+
89
+ ==Sample:
90
+
91
+ group(:default) do |g|
92
+ g.add('gem1')
93
+ g.add('gem2', :version => '1.2.3')
94
+ g.add('gem3', :source => 'http://gems.github.com')
95
+ g.add('gem4', :require => 'gem-four')
96
+ g.add('gem5', :require => ['gem-five', 'gemfive'])
97
+ g.add('gem6', :load => false)
98
+ end
99
+
100
+ group(:production, :dependencies => :default) do |g|
101
+ g.add('gem3', :load => false)
102
+ g.remove('gem1')
103
+ g.add('gem4', :source => 'http://gems.example.org')
104
+ end
105
+
106
+ group(:development, :dependencies => :default) do |g|
107
+ g.add('gem7', :version => '>=1.2.3.4', :load => false, :require => 'gemseven')
108
+ end
109
+
110
+ group(:test, :dependencies => :development, :source => 'http://gems.example.com') do |g|
111
+ g.add('gem8')
112
+ end
113
+
114
+ group(:staging) do |g|
115
+ g.add('gem2', :version => '3.2.1')
116
+ g.dependency(:development)
117
+ g.add('gem7', :load => true)
118
+ end
data/bin/gemtronics ADDED
@@ -0,0 +1,100 @@
1
+ #!/opt/local/bin/ruby
2
+ command_message = %{
3
+ Available commands:
4
+ - install <group> <path> # Specify the group of gems to install. The default is 'default' You must all specify the path to the gemtronics file you wish to install from. The default is 'config/gemtronics.rb'
5
+ - generate <path> # Specify where you would like the gemtronics file generated. The default 'config/gemtronics.rb'
6
+ - convert <path> # Convert an existing Gemtools yml file to Gemtronics. The default is 'config/gems.yml'
7
+ }.strip
8
+
9
+ command = ARGV[0]
10
+ if command.nil?
11
+ puts %{
12
+ You MUST specify a command!
13
+
14
+ #{command_message}
15
+ }.strip
16
+ exit(-1)
17
+ end
18
+
19
+ require 'rubygems'
20
+ require 'gemtronics'
21
+ require 'fileutils'
22
+ require 'yaml'
23
+
24
+ case command
25
+ when 'install'
26
+ path = ARGV[2] || File.join('config', 'gemtronics.rb')
27
+ Gemtronics.load(path)
28
+ Gemtronics.install_gems(ARGV[1] || 'default')
29
+ when 'generate'
30
+ path = ARGV[1] || 'config'
31
+ FileUtils.mkdir_p(path)
32
+ File.open(File.join(path, 'gemtronics.rb'), 'w') do |f|
33
+ f.puts %{
34
+ group(:default) do |g|
35
+ # g.add('gem name here')
36
+ # g.add('gem name here', :version => '1.2.3')
37
+ # g.add('gem name here', :version => '1.2.3', :source => 'http://gems.example.com')
38
+ # g.add('gem name here', :version => '1.2.3', :source => 'http://gems.example.com', :require => ['file1', 'file2'])
39
+ end
40
+
41
+ group(:production, :dependencies => :default) do |g|
42
+
43
+ end
44
+
45
+ group(:development, :dependencies => :default) do |g|
46
+
47
+ end
48
+
49
+ group(:test, :dependencies => :development) do |g|
50
+
51
+ end
52
+ }.strip
53
+ end
54
+ when 'convert'
55
+ path = ARGV[1] || File.join('config', 'gems.yml')
56
+ path = File.join(path, 'gems.yml') unless path.match(/gems.yml$/)
57
+ gem_list = YAML.load(File.read(path))
58
+ top_options = {}
59
+ gems = []
60
+ gem_list.each do |key, value|
61
+ if key == 'gems'
62
+ gems = value
63
+ else
64
+ top_options[key.to_sym] = value
65
+ end
66
+ end
67
+
68
+ out_path = path.gsub('gems.yml', 'gemtronics.rb')
69
+ File.open(out_path, 'w') do |f|
70
+ unless top_options.empty?
71
+ f.puts "group(:default, #{top_options.inspect.gsub('=>', ' => ')}) do |g|"
72
+ else
73
+ f.puts "group(:default) do |g|"
74
+ end
75
+
76
+ gems.each do |gemdef|
77
+ x = " g.add('#{gemdef['name']}'"
78
+ options = {}
79
+ options[:require] = gemdef['require_name'] if gemdef['require_name']
80
+ options[:version] = gemdef['version'] if gemdef['version']
81
+ options[:load] = false if gemdef['load'] == false
82
+ unless options.empty?
83
+ x << ", #{options.inspect.gsub('=>', ' => ')})"
84
+ else
85
+ x << ')'
86
+ end
87
+ f.puts x
88
+ end
89
+
90
+ f.puts 'end'
91
+ end
92
+ puts File.read(out_path)
93
+ else
94
+ puts %{
95
+ You entered an UNKNOWN command '#{command}'!
96
+
97
+ #{command_message}
98
+ }.strip
99
+ exit(-1)
100
+ end
@@ -0,0 +1,11 @@
1
+ module Gemtronics # :nodoc:
2
+
3
+ class << self
4
+
5
+ def method_missing(sym, *args) # :nodoc:
6
+ Gemtronics::Manager.instance.send(sym, *args)
7
+ end
8
+
9
+ end
10
+
11
+ end # Gemtronics
@@ -0,0 +1,126 @@
1
+ module Gemtronics
2
+ # This class is yielded up when you create/modify a group.
3
+ # This class holds all the relevant information about the gems
4
+ # for the defined group.
5
+ #
6
+ # See Gemtronics::Manager for more details on creating a group.
7
+ class Grouper
8
+ # The Array of gems belonging to this group.
9
+ attr_accessor :gems
10
+ # A Hash representing the default options for this group.
11
+ attr_accessor :group_options
12
+
13
+ # Creates a new Gemtronics::Grouper class. It takes a Hash
14
+ # of options that will be applied to all gems added to the group.
15
+ # These options will be merged with Gemtronics::Manager::GLOBAL_DEFAULT_OPTIONS
16
+ #
17
+ # This also takes a special option <tt>:dependencies</tt> which can
18
+ # be an Array of other groups to inherit gems from.
19
+ #
20
+ # Example:
21
+ # group(:development) do |g|
22
+ # g.add('gem1')
23
+ # end
24
+ #
25
+ # group(:test, :dependencies => :development) do |g|
26
+ # g.add('gem2')
27
+ # g.add('gem3')
28
+ # end
29
+ #
30
+ # In this example the <tt>:test</tt> group would
31
+ # now have the following gems: <tt>gem1, gem2, gem3</tt>
32
+ def initialize(options = {})
33
+ self.gems = []
34
+ options = {} if options.nil?
35
+ deps = options.delete(:dependencies)
36
+ if deps
37
+ [deps].flatten.each do |dep|
38
+ self.dependency(dep)
39
+ end
40
+ end
41
+ self.group_options = Gemtronics::Manager::GLOBAL_DEFAULT_OPTIONS.merge(options)
42
+ self
43
+ end
44
+
45
+ # Adds a gem to the group. All that is required is the name of the gem.
46
+ #
47
+ # The following is a list of the options that can be passed in:
48
+ # :require # a String or Array of file(s) to be required by the system
49
+ # :version # a String representing the version number of the gem.
50
+ # :source # a String representing the source URL of where the gem lives
51
+ # :load # true/false the files specified by the :require option should be loaded
52
+ #
53
+ # These options get merged with the group options and the global options.
54
+ #
55
+ # Example:
56
+ # group(:default, :version => '>=1.0.0') do |g|
57
+ # g.add('gem1', :source => 'http://gems.example.com')
58
+ # g.add('gem2', :version => '0.9.8')
59
+ # g.add('gem3', :require => ['gem-three', 'gem3'], :version => '>2.0.0')
60
+ # g.add('gem4', :require => 'gemfour', :load => false)
61
+ # end
62
+ #
63
+ # # => [{:name => 'gem1', :version => '>=1.0.0', :source => 'http://gems.example.com',
64
+ # :require => ['gem1'], :load => true},
65
+ # {:name => 'gem2', :version => '0.9.8', :source => 'http://gems.rubyforge.org',
66
+ # :require => ['gem2'], :load => true},
67
+ # {:name => 'gem3', :version => '>2.0.0', :source => 'http://gems.rubyforge.org',
68
+ # :require => ['gem-three', 'gem3'], :load => true},
69
+ # {:name => 'gem4', :version => '>=1.0.0', :source => 'http://gems.rubyforge.org',
70
+ # :require => ['gemfour']}, :load => false]
71
+ def add(name, options = {})
72
+ g = self.group_options.merge({:name => name.to_s, :require => [name.to_s]}.merge(options))
73
+ g[:require] = [g[:require]].flatten
74
+ self.gems << g
75
+ end
76
+
77
+ # Removes a gem from the group.
78
+ #
79
+ # Example:
80
+ # group(:development) do |g|
81
+ # g.add('gem1')
82
+ # g.add('gem2')
83
+ # end
84
+ #
85
+ # group(:test, :dependencies => :development) do |g|
86
+ # g.add('gem3')
87
+ # g.remove('gem2')
88
+ # g.add('gem4')
89
+ # end
90
+ #
91
+ # In this example the <tt>:test</tt> group would
92
+ # now have the following gems: <tt>gem1, gem3, gem4</tt>
93
+ def remove(name)
94
+ self.gems.each do |g|
95
+ if g[:name] = name.to_s
96
+ self.gems.delete(g)
97
+ break
98
+ end
99
+ end
100
+ end
101
+
102
+ # Injects another groups gems into this group.
103
+ #
104
+ # Example:
105
+ # group(:development) do |g|
106
+ # g.add('gem1')
107
+ # end
108
+ #
109
+ # group(:test) do |g|
110
+ # g.add('gem2')
111
+ # g.dependency(:development)
112
+ # g.add('gem3')
113
+ # end
114
+ #
115
+ # In this example the <tt>:test</tt> group would
116
+ # now have the following gems: <tt>gem2, gem1, gem3</tt>
117
+ def dependency(name)
118
+ group = Gemtronics::Manager.instance.groups[name.to_sym]
119
+ if group
120
+ self.gems << group.gems.dup
121
+ self.gems.flatten!
122
+ end
123
+ end
124
+
125
+ end # Grouper
126
+ end # Gemtronics
@@ -0,0 +1,163 @@
1
+ module Gemtronics
2
+ class Manager
3
+ include Singleton
4
+
5
+ # A Hash of the default options that are applied to all the gems.
6
+ # These options can be overidden at both the group and the individual
7
+ # gem level.
8
+ GLOBAL_DEFAULT_OPTIONS = {:load => true, :version => '>=0.0.0', :source => 'http://gems.rubyforge.org'}
9
+
10
+ # A Hash of all the groups that have been defined.
11
+ attr_accessor :groups
12
+
13
+ def initialize # :nodoc:
14
+ reset!
15
+ end
16
+
17
+ # Creates, or reopens a new group of gems. It takes the name of the
18
+ # group, and any options you would like all of the gems in that group
19
+ # to inherit.
20
+ #
21
+ # Example:
22
+ # group(:development, :source => 'http://gems.example.com') do |g|
23
+ # g.add('gem1')
24
+ # g.add('gem2')
25
+ # end
26
+ #
27
+ # For more information see Gemtronics::Grouper
28
+ def group(name, options = {})
29
+ name = name.to_sym
30
+ options = GLOBAL_DEFAULT_OPTIONS.merge(options)
31
+ g = (self.groups[name] ||= Gemtronics::Grouper.new(options))
32
+ yield g if block_given?
33
+ end
34
+
35
+ # Aliases one gem group to another group.
36
+ #
37
+ # Example:
38
+ # group(:development) do |g|
39
+ # g.add('gem1')
40
+ # g.add('gem2')
41
+ # end
42
+ #
43
+ # alias_group :test, :development
44
+ #
45
+ # The result would be the same as if you had done this:
46
+ #
47
+ # group(:development) do |g|
48
+ # g.add('gem1')
49
+ # g.add('gem2')
50
+ # end
51
+ # group(:test, :dependencies => :development) do |g|
52
+ # end
53
+ def alias_group(name, src)
54
+ group(name, :dependencies => src)
55
+ end
56
+
57
+ # Reads in a file and sets up the gems appropriately.
58
+ # The default path is <tt>'<pwd>/config/gemtronics.rb'</tt>
59
+ #
60
+ # See README for an example file.
61
+ def load(file = File.join(FileUtils.pwd, 'config', 'gemtronics.rb'))
62
+ eval(File.read(file), binding)
63
+ end
64
+
65
+ # Requires all the gems and the specified files for the group.
66
+ # It will not require any gems that have the <tt>:load</tt>
67
+ # options set to <tt>false</tt>
68
+ #
69
+ # Example:
70
+ # group(:default) do |g|
71
+ # g.add('gem1')
72
+ # g.add('gem2', :version => '1.2.3')
73
+ # g.add('gem3', :load => false)
74
+ # g.add('gem4', :require => 'gem-four')
75
+ # g.add('gem5', :require => ['gem-five', 'gemfive'])
76
+ # g.add('gem6', :load => false)
77
+ # end
78
+ #
79
+ # Gemtronics.require_gems(:default)
80
+ #
81
+ # In this example it would do the following:
82
+ #
83
+ # gem('gem1', '>=0.0.0')
84
+ # require 'gem1'
85
+ # gem('gem2', '1.2.3')
86
+ # require 'gem2'
87
+ # gem('gem4', '>=0.0.0')
88
+ # require 'gem-four'
89
+ # gem('gem5', '>=0.0.0')
90
+ # require 'gem-five'
91
+ # require 'gemfive'
92
+ def require_gems(group = :default, options = {})
93
+ group = self.groups[group.to_sym]
94
+ return if group.nil?
95
+ options = {:verbose => false}.merge(options)
96
+ group.gems.each do |g|
97
+ if g[:load] == true
98
+ gem(g[:name], g[:version])
99
+ g[:require].each do |f|
100
+ puts "require #{f}" if options[:verbose]
101
+ require f
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # This will install only the gems in the group that
108
+ # are not currently installed in the system.
109
+ #
110
+ # Example:
111
+ # group(:default) do |g|
112
+ # g.add('gem1')
113
+ # g.add('gem2', :version => '1.2.3')
114
+ # g.add('gem3', :load => false)
115
+ # g.add('gem4', :require => 'gem-four')
116
+ # g.add('gem5', :require => ['gem-five', 'gemfive'])
117
+ # g.add('gem6', :load => false, :source => 'http://gems.example.com')
118
+ # end
119
+ #
120
+ # Assuming gems <tt>gem3, gem4, gem5</tt> are previously installed:
121
+ #
122
+ # Gemtronics.install_gems(:default)
123
+ # # gem install gem1 --source=http://gems.rubyforge.org
124
+ # # gem install gem2 --source=http://gems.rubyforge.org --version=1.2.3
125
+ # # gem install gem6 --source=http://gems.example.com
126
+ def install_gems(group = :default)
127
+ group = self.groups[group.to_sym]
128
+ return if group.nil?
129
+
130
+ group.gems.each do |g|
131
+ unless gem_installed?(g[:name], g[:version])
132
+ cmd = "gem install #{g[:name]} --source=#{g[:source]}"
133
+ unless g[:version].match(/^(\>\=|\>)/)
134
+ cmd << " --version=#{g[:version]}"
135
+ end
136
+ system cmd
137
+ end
138
+ end
139
+ end
140
+
141
+ def install_all_gems # :nodoc:
142
+ self.groups.each do |name, value|
143
+ self.install_gems(name)
144
+ end
145
+ end
146
+
147
+ def reset! # :nodoc:
148
+ self.groups = {}
149
+ end
150
+
151
+ private
152
+ def gem_installed?(name, version) # :nodoc:
153
+ begin
154
+ gem(name, version)
155
+ return true
156
+ rescue Gem::LoadError => e
157
+ return true if e.message.match(/can't activate/)
158
+ return false
159
+ end
160
+ end
161
+
162
+ end # Manager
163
+ end # Gemtronics
data/lib/gemtronics.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'singleton'
2
+ Dir.glob(File.join(File.dirname(__FILE__), 'gemtronics', '**/*.rb')).each do |f|
3
+ require File.expand_path(f)
4
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gemtronics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - markbates
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-13 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: "gemtronics was developed by: markbates"
17
+ email: ""
18
+ executables:
19
+ - gemtronics
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - LICENSE
25
+ files:
26
+ - lib/gemtronics/gemtronics.rb
27
+ - lib/gemtronics/grouper.rb
28
+ - lib/gemtronics/manager.rb
29
+ - lib/gemtronics.rb
30
+ - README
31
+ - LICENSE
32
+ has_rdoc: true
33
+ homepage: ""
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: magrathea
56
+ rubygems_version: 1.3.4
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: gemtronics
60
+ test_files: []
61
+