hubless 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -4,7 +4,7 @@ Search your local gem repository for gems installed from GitHub that have since
4
4
 
5
5
  ## Command line usage
6
6
 
7
- $ hubless
7
+ $ hubless [-i|-h]
8
8
 
9
9
  ## Sample output
10
10
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.2.0
data/hubless.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hubless}
8
- s.version = "0.1.3"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Greg Sterndale"]
data/lib/application.rb CHANGED
@@ -4,14 +4,39 @@ class Hubless
4
4
  class Application
5
5
 
6
6
  def self.run(*args)
7
- hubless = Hubless.new
8
- hubless.gem_breakdown
9
- hubless.github_repos
10
- hubless.gemcutter_gems
11
- hubless.uninstall_instructions
12
- hubless.install_instructions
7
+ if help_option?(args)
8
+ display_help
9
+ else
10
+ hubless = Hubless.new
11
+ hubless.gem_breakdown
12
+ hubless.github_repos
13
+ hubless.gemcutter_gems
14
+ hubless.uninstall_instructions
15
+ if install_option?(args)
16
+ hubless.install_gems
17
+ else
18
+ hubless.install_instructions
19
+ end
20
+ end
13
21
  return 0
14
22
  end
23
+
24
+ protected
15
25
 
26
+ def self.display_help
27
+ $stdout.puts "Search your local gem repository for gems installed from GitHub that have since moved to Gemcutter"
28
+ $stdout.puts "Usage: hubless [-i|-h] "
29
+ $stdout.puts "\t-i, --install\tinstall GitHub gems that are on Gemcutter (consider running with sudo)"
30
+ $stdout.puts "\t-h, --help\tdisplay this help and exit"
31
+ end
32
+
33
+ def self.install_option?(args)
34
+ args.include?('-i') || args.include?('--install')
35
+ end
36
+
37
+ def self.help_option?(args)
38
+ args.include?('-h') || args.include?('--help')
39
+ end
40
+
16
41
  end
17
42
  end
@@ -2,141 +2,141 @@ require 'rubygems'
2
2
  require 'net/http'
3
3
 
4
4
  class Hubless
5
- ServiceError = Class.new(RuntimeError)
5
+ class ServiceError < StandardError; end
6
6
 
7
- class GemDescription
7
+ class GemDescription
8
8
 
9
- attr_reader :name
10
- attr_accessor :version
9
+ attr_reader :name
10
+ attr_accessor :version
11
11
 
12
- # GemDescriptions of all gems installed locally
13
- def self.local_gems
14
- @@local_gems ||= Gem.cache.map {|g| new(g.first) }.sort!{|x,y| y.name <=> x.name }
15
- end
12
+ # GemDescriptions of all gems installed locally
13
+ def self.local_gems
14
+ @@local_gems ||= Gem.cache.map {|g| new(g.first) }.sort!{|x,y| y.name <=> x.name }
15
+ end
16
16
 
17
- # New GemDescription from a one-liner or options Hash
18
- # Hubless::GemDescription.new('my-awesome_gem-3.4.5')
19
- # Hubless::GemDescription.new(:name => 'my-awesome_gem', :version => '3.4.5')
20
- def initialize(*args)
21
- case args.first
22
- when String
23
- self.attributes_from_one_liner(args.first)
24
- when Hash
25
- self.name = args.first[:name]
26
- self.version = args.first[:version]
17
+ # New GemDescription from a one-liner or options Hash
18
+ # Hubless::GemDescription.new('my-awesome_gem-3.4.5')
19
+ # Hubless::GemDescription.new(:name => 'my-awesome_gem', :version => '3.4.5')
20
+ def initialize(*args)
21
+ case args.first
22
+ when String
23
+ self.attributes_from_one_liner(args.first)
24
+ when Hash
25
+ self.name = args.first[:name]
26
+ self.version = args.first[:version]
27
+ end
27
28
  end
28
- end
29
29
 
30
- # Assign gem description name and clear any cached values
31
- def name=(str)
32
- self.clear
33
- @name = str
34
- end
30
+ # Assign gem description name and clear any cached values
31
+ def name=(str)
32
+ self.clear
33
+ @name = str
34
+ end
35
35
 
36
- # Does a repo exist on GitHub that matches this gem
37
- def github?
38
- if @is_github.nil?
39
- @is_github = (self.github_like? && self.github_repo_exist?)
40
- else
41
- @is_github
36
+ # Does a repo exist on GitHub that matches this gem
37
+ def github?
38
+ if @is_github.nil?
39
+ @is_github = (self.github_like? && self.github_repo_exist?)
40
+ else
41
+ @is_github
42
+ end
42
43
  end
43
- end
44
44
 
45
- # Full name of this gem including GitHub username
46
- def github_name
47
- self.name if self.github_user_name
48
- end
45
+ # Full name of this gem including GitHub username
46
+ def github_name
47
+ self.name if self.github_user_name
48
+ end
49
49
 
50
- def github_like?
51
- self.github_user_name && self.github_repo_name
52
- end
50
+ def github_like?
51
+ self.github_user_name && self.github_repo_name
52
+ end
53
53
 
54
- # Does a gem exist on Gemcutter that matches this gem
55
- def gemcutter?
56
- if @is_gemcutter.nil?
57
- @is_gemcutter = self.gemcutter_gem_exist?
58
- else
59
- @is_gemcutter
54
+ # Does a gem exist on Gemcutter that matches this gem
55
+ def gemcutter?
56
+ if @is_gemcutter.nil?
57
+ @is_gemcutter = self.gemcutter_gem_exist?
58
+ else
59
+ @is_gemcutter
60
+ end
60
61
  end
61
- end
62
62
 
63
- # Likely name of this gem on Gemcutter (without the GitHub username)
64
- def gemcutter_name
65
- self.github? ? self.github_repo_name : self.name
66
- end
63
+ # Likely name of this gem on Gemcutter (without the GitHub username)
64
+ def gemcutter_name
65
+ self.github? ? self.github_repo_name : self.name
66
+ end
67
67
 
68
- # Command to install gem from Gemcutter
69
- def install_cmd
70
- cmd = ["gem install"]
71
- cmd << self.gemcutter_name
72
- cmd << "-v #{self.version}" if self.version
73
- cmd.join(' ')
74
- end
68
+ # Command to install gem from Gemcutter
69
+ def install_cmd
70
+ cmd = ["gem install"]
71
+ cmd << self.gemcutter_name
72
+ cmd << "-v #{self.version}" if self.version
73
+ cmd.join(' ')
74
+ end
75
75
 
76
- # Command to uninstall gem
77
- def uninstall_cmd
78
- cmd = ["gem uninstall"]
79
- cmd << self.name
80
- cmd << "-v #{self.version}" if self.version
81
- cmd.join(' ')
82
- end
76
+ # Command to uninstall gem
77
+ def uninstall_cmd
78
+ cmd = ["gem uninstall"]
79
+ cmd << self.name
80
+ cmd << "-v #{self.version}" if self.version
81
+ cmd.join(' ')
82
+ end
83
83
 
84
- protected
84
+ protected
85
85
 
86
- def clear
87
- @is_gemcutter = @is_github = nil
88
- end
86
+ def clear
87
+ @is_gemcutter = @is_github = nil
88
+ end
89
89
 
90
- def github_user_name
91
- if self.name =~ /^([^-]*)-.*$/
92
- $1
90
+ def github_user_name
91
+ if self.name =~ /^([^-]*)-.*$/
92
+ $1
93
+ end
93
94
  end
94
- end
95
95
 
96
- def github_repo_name
97
- if self.name =~ /^[^-]*-(.*)$/
98
- $1
96
+ def github_repo_name
97
+ if self.name =~ /^[^-]*-(.*)$/
98
+ $1
99
+ end
99
100
  end
100
- end
101
101
 
102
- def github_uri
103
- URI.parse("http://github.com/api/v2/yaml/repos/show/#{self.github_user_name}/#{self.github_repo_name}")
104
- end
102
+ def github_uri
103
+ URI.parse("http://github.com/api/v2/yaml/repos/show/#{self.github_user_name}/#{self.github_repo_name}")
104
+ end
105
105
 
106
- def github_repo_exist?
107
- response = Net::HTTP.get(self.github_uri)
108
- case
109
- when response =~ /error: repository not found/
110
- false
111
- when response =~ /error: too many requests/
112
- raise ServiceError
113
- else
114
- true
106
+ def github_repo_exist?
107
+ response = Net::HTTP.get(self.github_uri)
108
+ case
109
+ when response =~ /error: repository not found/
110
+ false
111
+ when response =~ /error: too many requests/
112
+ raise ServiceError
113
+ else
114
+ true
115
+ end
115
116
  end
116
- end
117
117
 
118
- def gemcutter_uri
119
- URI.parse("http://gemcutter.org/api/v1/gems/#{self.name}.json")
120
- end
118
+ def gemcutter_uri
119
+ URI.parse("http://gemcutter.org/api/v1/gems/#{self.name}.json")
120
+ end
121
121
 
122
- def gemcutter_gem_exist?
123
- response = Net::HTTP.get(self.gemcutter_uri)
124
- case
125
- when response =~ /This rubygem could not be found./
126
- false
127
- when response =~ /error: too many requests/
128
- raise ServiceError
129
- else
130
- true
122
+ def gemcutter_gem_exist?
123
+ response = Net::HTTP.get(self.gemcutter_uri)
124
+ case
125
+ when response =~ /This rubygem could not be found./
126
+ false
127
+ when response =~ /error: too many requests/
128
+ raise ServiceError
129
+ else
130
+ true
131
+ end
131
132
  end
132
- end
133
133
 
134
- def attributes_from_one_liner(one_liner)
135
- if one_liner =~ /^(.*)-([\d\.]+)$/
136
- self.name = $1
137
- self.version = $2
134
+ def attributes_from_one_liner(one_liner)
135
+ if one_liner =~ /^(.*)-([\d\.]+)$/
136
+ self.name = $1
137
+ self.version = $2
138
+ end
138
139
  end
139
- end
140
140
 
141
- end
141
+ end
142
142
  end
data/lib/hubless.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  require File.dirname(__FILE__) + '/gem_description'
2
2
 
3
+
4
+
3
5
  class Hubless
6
+ class GemInstallError < StandardError; end
7
+
4
8
  @@io = $stdout
5
9
  @@timeout = 1
6
10
 
@@ -55,14 +59,16 @@ class Hubless
55
59
  self.gems.each {|g| @@io.puts(g.install_cmd) if g.github? && g.gemcutter? }
56
60
  end
57
61
 
58
- # def self.reinstall_gems
59
- # self.gems.each do |g|
60
- # if g.github? && g.gemcutter?
61
- # @@io.puts %x(#{g.uninstall_cmd})
62
- # @@io.puts %x(#{g.install_cmd})
63
- # end
64
- # end
65
- # end
62
+ def install_gems
63
+ @@io.puts("\nInstalling gems:")
64
+ self.gems.each do |g|
65
+ if g.github? && g.gemcutter?
66
+ cmd = g.install_cmd
67
+ @@io.puts cmd
68
+ raise GemInstallError unless Kernel.system(cmd)
69
+ end
70
+ end
71
+ end
66
72
 
67
73
  protected
68
74
 
@@ -71,5 +77,3 @@ protected
71
77
  end
72
78
 
73
79
  end
74
-
75
- # Hubless.local_gems_on_github.each{|g| puts g.inspect }
@@ -14,4 +14,28 @@ class TestApplication < Test::Unit::TestCase
14
14
  Hubless::Application.run
15
15
  end
16
16
 
17
+ def test_run_with_i
18
+ hubless = mock(
19
+ :gem_breakdown => true,
20
+ :github_repos => true,
21
+ :gemcutter_gems => true,
22
+ :uninstall_instructions => true,
23
+ :install_gems => true
24
+ )
25
+ Hubless.expects(:new).returns(hubless)
26
+ Hubless::Application.run('-i')
27
+ end
28
+
29
+ def test_run_with_h
30
+ original_stdout = $stdout
31
+ fake_stdout = mock
32
+ fake_stdout.stubs(:write)
33
+ $stdout = fake_stdout
34
+ fake_stdout.expects(:puts).at_least_once
35
+ Hubless.expects(:new).never
36
+ Hubless::Application.run('-h')
37
+ ensure
38
+ $stdout = original_stdout
39
+ end
40
+
17
41
  end
data/test/test_hubless.rb CHANGED
@@ -98,99 +98,34 @@ class TestHubless < Test::Unit::TestCase
98
98
  hubless.install_instructions
99
99
  end
100
100
 
101
-
102
- # def setup
103
- # @gems = [
104
- # [ 'my-github_and_gemcutter_gem-0.1.2', mock ],
105
- # [ 'my-github_only_gem-1.2.3', mock ],
106
- # [ 'my-github_look_a_like_on_gemcutter_gem-2.3.4', mock ],
107
- # [ 'my_non_github_gem-3.4.5', mock ]
108
- # ]
109
- # Gem.stubs(:cache).returns(@gems)
110
- # end
111
- #
112
- # def teardown
113
- # Hubless.clear
114
- # end
115
- #
116
- # def test_local_gems
117
- # local_gems = Hubless.local_gems
118
- # assert local_gems.detect{|gem_description| gem_description.name == 'my-github_and_gemcutter_gem' }
119
- # assert local_gems.detect{|gem_description| gem_description.name == 'my-github_only_gem' }
120
- # assert local_gems.detect{|gem_description| gem_description.name == 'my-github_look_a_like_on_gemcutter_gem' }
121
- # assert local_gems.detect{|gem_description| gem_description.name == 'my_non_github_gem' }
122
- # assert_equal @gems.length, local_gems.length
123
- # end
124
- #
125
- # def test_local_github_like_gems
126
- # local_github_like_gems = Hubless.local_github_like_gems
127
- # assert local_github_like_gems.detect{|gem_description| gem_description.name == 'my-github_and_gemcutter_gem' }
128
- # assert local_github_like_gems.detect{|gem_description| gem_description.name == 'my-github_only_gem' }
129
- # assert local_github_like_gems.detect{|gem_description| gem_description.name == 'my-github_look_a_like_on_gemcutter_gem' }
130
- # assert ! local_github_like_gems.detect{|gem_description| gem_description.name == 'my_non_github_gem' }
131
- # end
132
- #
133
- # def test_local_gems_on_github
134
- # Net::HTTP.expects(:get).times(3).
135
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
136
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
137
- # returns("--- \nerror: \n- error: repository not found\n")
138
- # local_gems_on_github = Hubless.local_gems_on_github
139
- # assert local_gems_on_github.detect{|gem_description| gem_description.name == 'my-github_and_gemcutter_gem' }
140
- # assert local_gems_on_github.detect{|gem_description| gem_description.name == 'my-github_only_gem' }
141
- # assert ! local_gems_on_github.detect{|gem_description| gem_description.name == 'my-github_look_a_like_on_gemcutter_gem' }
142
- # assert ! local_gems_on_github.detect{|gem_description| gem_description.name == 'my_non_github_gem' }
143
- # end
144
- #
145
- # def test_local_gems_on_github_with_github_error
146
- # Net::HTTP.expects(:get).times(2).
147
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
148
- # returns("--- \nerror: \n- error: too many requests\n")
149
- # assert_raise(ServiceError) { Hubless.local_gems_on_github }
150
- # end
151
- #
152
- # def test_local_gems_on_github_and_gemcutter
153
- # Net::HTTP.expects(:get).times(5).
154
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
155
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
156
- # returns("--- \nerror: \n- error: repository not found\n").
157
- # returns(%Q{{"version_downloads":137674,"info":" Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick\n on top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates.\n","project_uri":"http://gemcutter.org/gems/rails","name":"rails","version":"2.3.5","gem_uri":"http://gemcutter.org/gems/rails-2.3.5.gem","downloads":218523,"authors":"David Heinemeier Hansson"}}).
158
- # returns("This rubygem could not be found.")
159
- # local_gems_on_github_and_gemcutter = Hubless.local_gems_on_github_and_gemcutter
160
- # assert local_gems_on_github_and_gemcutter.detect{|gem_description| gem_description.name == 'my-github_and_gemcutter_gem' }
161
- # assert ! local_gems_on_github_and_gemcutter.detect{|gem_description| gem_description.name == 'my-github_only_gem' }
162
- # assert ! local_gems_on_github_and_gemcutter.detect{|gem_description| gem_description.name == 'my-github_look_a_like_on_gemcutter_gem' }
163
- # assert ! local_gems_on_github_and_gemcutter.detect{|gem_description| gem_description.name == 'my_non_github_gem' }
164
- # end
165
- #
166
- # def test_clear
167
- # Net::HTTP.expects(:get).times(5).
168
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
169
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
170
- # returns("--- \nerror: \n- error: repository not found\n").
171
- # returns(%Q{{"version_downloads":137674,"info":" Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick\n on top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates.\n","project_uri":"http://gemcutter.org/gems/rails","name":"rails","version":"2.3.5","gem_uri":"http://gemcutter.org/gems/rails-2.3.5.gem","downloads":218523,"authors":"David Heinemeier Hansson"}}).
172
- # returns("This rubygem could not be found.")
173
- #
174
- # Hubless.local_gems_on_github_and_gemcutter
175
- #
176
- # Net::HTTP.expects(:get).times(0)
177
- #
178
- # Hubless.local_gems_on_github_and_gemcutter
179
- #
180
- # Hubless.clear
181
- #
182
- # Net::HTTP.expects(:get).times(5).
183
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
184
- # returns("--- \nrepository: \n :description: Description here\n :forks: 0\n :url: http://github.com/some_user/some_repo\n :fork: false\n :open_issues: 0\n :watchers: 1\n :private: false\n :name: some_repo\n :owner: some_user\n").
185
- # returns("--- \nerror: \n- error: repository not found\n").
186
- # returns(%Q{{"version_downloads":137674,"info":" Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick\n on top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates.\n","project_uri":"http://gemcutter.org/gems/rails","name":"rails","version":"2.3.5","gem_uri":"http://gemcutter.org/gems/rails-2.3.5.gem","downloads":218523,"authors":"David Heinemeier Hansson"}}).
187
- # returns("This rubygem could not be found.")
188
- #
189
- # Hubless.local_gems_on_github_and_gemcutter
190
- # end
191
- def test_nothin
192
- assert true
193
- end
194
-
101
+ def test_install_gems
102
+ local_gems = [
103
+ mock(:install_cmd => 'foo', :github? => true, :gemcutter? => true),
104
+ mock(:install_cmd => 'bar', :github? => true, :gemcutter? => true),
105
+ mock(:install_cmd => 'abc', :github? => true, :gemcutter? => true),
106
+ mock(:github? => true, :gemcutter? => false),
107
+ mock(:github? => false)
108
+ ]
109
+ Hubless::GemDescription.expects(:local_gems).once.returns(local_gems)
110
+ @io.expects(:puts).with{|s| s =~ /Installing gems:/ }
111
+ @io.expects(:puts).once.with{|s| s =~ /foo/ }
112
+ @io.expects(:puts).once.with{|s| s =~ /bar/ }
113
+ @io.expects(:puts).once.with{|s| s =~ /abc/ }
114
+ Kernel.expects(:system).once.with{|s| s =~ /foo/ }.returns(true)
115
+ Kernel.expects(:system).once.with{|s| s =~ /bar/ }.returns(true)
116
+ Kernel.expects(:system).once.with{|s| s =~ /abc/ }.returns(true)
117
+ hubless = Hubless.new
118
+ hubless.install_gems
119
+
120
+ local_gems = [
121
+ mock(:install_cmd => 'foo', :github? => true, :gemcutter? => true)
122
+ ]
123
+ Hubless::GemDescription.expects(:local_gems).once.returns(local_gems)
124
+ @io.expects(:puts).with{|s| s =~ /Installing gems:/ }
125
+ @io.expects(:puts).once.with{|s| s =~ /foo/ }
126
+ Kernel.expects(:system).once.with{|s| s =~ /foo/ }.returns(false)
127
+ hubless = Hubless.new
128
+ assert_raise(Hubless::GemInstallError) { hubless.install_gems }
129
+ end
195
130
 
196
131
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Sterndale