gem-dependent 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'rspec', '~>2'
5
+ gem 'jeweler'
6
+ gem 'parallel'
data/Gemfile.lock ADDED
@@ -0,0 +1,34 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ gemcutter (0.6.1)
6
+ git (1.2.5)
7
+ jeweler (1.4.0)
8
+ gemcutter (>= 0.1.0)
9
+ git (>= 1.2.5)
10
+ rubyforge (>= 2.0.0)
11
+ json_pure (1.4.6)
12
+ parallel (0.5.0)
13
+ rake (0.8.7)
14
+ rspec (2.0.1)
15
+ rspec-core (~> 2.0.1)
16
+ rspec-expectations (~> 2.0.1)
17
+ rspec-mocks (~> 2.0.1)
18
+ rspec-core (2.0.1)
19
+ rspec-expectations (2.0.1)
20
+ diff-lcs (>= 1.1.2)
21
+ rspec-mocks (2.0.1)
22
+ rspec-core (~> 2.0.1)
23
+ rspec-expectations (~> 2.0.1)
24
+ rubyforge (2.0.4)
25
+ json_pure (>= 1.1.7)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ jeweler
32
+ parallel
33
+ rake
34
+ rspec (~> 2)
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ task :default => :spec
2
+ require "rspec/core/rake_task"
3
+ RSpec::Core::RakeTask.new(:spec) do |t|
4
+ t.rspec_opts = '--backtrace --color'
5
+ end
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.name = 'gem-dependent'
11
+ gem.summary = "See which gems depend on your gems"
12
+ gem.email = "grosser.michael@gmail.com"
13
+ gem.homepage = "http://github.com/grosser/#{gem.name}"
14
+ gem.authors = ["Michael Grosser"]
15
+ end
16
+
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: gem install jeweler"
20
+ end
data/Readme.md ADDED
@@ -0,0 +1,42 @@
1
+ Install
2
+ =======
3
+ sudo gem install gem-dependent
4
+
5
+ Usage
6
+ =====
7
+ gem dependent my_gem
8
+
9
+ --source URL Query this source (e.g. http://rubygems.org)
10
+ --no-progress Do not show progress
11
+ --fetch-limit N Fetch specs for max N gems (for fast debugging)
12
+
13
+ Output
14
+ ======
15
+
16
+ $ gem dependent my_gem --source http://rubygems.org
17
+ other_gem >= 1.2.1
18
+ even_more = 0.0.1
19
+
20
+ $ gem dependent XXX --source http://rubygems.org --no-progress | wc -l
21
+
22
+ # Fun-facts from 2010-11-03
23
+ bundler: 263
24
+ activesupport: 983
25
+ activerecord: 566
26
+
27
+ hoe: 1454
28
+ jeweler: 234
29
+ echoe: 85
30
+
31
+ nokogiri: 516
32
+ hpricot: 297
33
+
34
+ TODO
35
+ =====
36
+ - include reverse dependencies (a > b > c --> a = [b,c])
37
+
38
+ Author
39
+ ======
40
+ [Michael Grosser](http://grosser.it)
41
+ grosser.michael@gmail.com
42
+ Hereby placed under public domain, do what you want, just do not hold me accountable...
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,46 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{gem-dependent}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Michael Grosser"]
12
+ s.date = %q{2010-11-03}
13
+ s.email = %q{grosser.michael@gmail.com}
14
+ s.files = [
15
+ "Gemfile",
16
+ "Gemfile.lock",
17
+ "Rakefile",
18
+ "Readme.md",
19
+ "VERSION",
20
+ "gem-dependent.gemspec",
21
+ "lib/rubygems/commands/dependent_command.rb",
22
+ "lib/rubygems/dependent.rb",
23
+ "lib/rubygems_plugin.rb",
24
+ "spec/dependent_spec.rb",
25
+ "spec/fixtures/gemcutter_specs.yml"
26
+ ]
27
+ s.homepage = %q{http://github.com/grosser/gem-dependent}
28
+ s.rdoc_options = ["--charset=UTF-8"]
29
+ s.require_paths = ["lib"]
30
+ s.rubygems_version = %q{1.3.7}
31
+ s.summary = %q{See which gems depend on your gems}
32
+ s.test_files = [
33
+ "spec/dependent_spec.rb"
34
+ ]
35
+
36
+ if s.respond_to? :specification_version then
37
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
38
+ s.specification_version = 3
39
+
40
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
41
+ else
42
+ end
43
+ else
44
+ end
45
+ end
46
+
@@ -0,0 +1,46 @@
1
+ require 'rubygems/command'
2
+ require 'rubygems/dependent'
3
+
4
+ class Gem::Commands::DependentCommand < Gem::Command
5
+ def initialize
6
+ super 'dependent', 'Show which gems depend on a gem', :progress => true
7
+
8
+ add_option('--source URL', 'Query these sources (e.g. http://gemcutter.org)') do |remote, _|
9
+ options[:source] = remote.to_s.split(',')
10
+ end
11
+
12
+ add_option('--no-progress', 'Do not show progress') do
13
+ options[:progress] = false
14
+ end
15
+
16
+ add_option('--fetch-limit N', Integer, 'Fetch specs for max N gems (for fast debugging)') do |limit, _|
17
+ options[:fetch_limit] = limit
18
+ end
19
+ end
20
+
21
+ def arguments
22
+ "GEMNAME which gems depend on a gem"
23
+ end
24
+
25
+ def usage
26
+ "#{program_name} GEMNAME"
27
+ end
28
+
29
+ def execute
30
+ gem = get_all_gem_names.first
31
+ gems_and_dependencies = Gem::Dependent.find(gem, options)
32
+ gems_and_dependencies.each do |gem, dependencies|
33
+ requirements = dependencies.map do |dependency|
34
+ formatted_dependency(dependency)
35
+ end.join(', ')
36
+ puts "#{gem} #{requirements}"
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def formatted_dependency(dependency)
43
+ type = " (#{dependency.type})" if dependency.type == :development
44
+ "#{dependency.requirement}#{type}"
45
+ end
46
+ end
@@ -0,0 +1,89 @@
1
+ require 'parallel'
2
+ require 'rubygems/spec_fetcher'
3
+
4
+ module Gem
5
+ class Dependent
6
+ VERSION = File.read( File.join(File.dirname(__FILE__),'..','..','VERSION') ).strip
7
+
8
+ def self.find(gem, options={})
9
+ specs_and_sources = with_changed_source(options[:source]) do
10
+ all_specs_and_sources
11
+ end
12
+
13
+ if options[:fetch_limit]
14
+ specs_and_sources = specs_and_sources.first(options[:fetch_limit])
15
+ end
16
+
17
+ puts "Downloading specs for #{specs_and_sources.size} gems" if options[:progress]
18
+
19
+ # fetch dependencies
20
+ gem_names_and_dependencies = Parallel.map(specs_and_sources, :in_processes => 20) do |spec_tuple, source_uri|
21
+ print '.' if options[:progress]
22
+ name = spec_tuple.first
23
+ dependencies = dependencies(spec_tuple, source_uri)
24
+ [name, dependencies]
25
+ end
26
+
27
+ print "\n" if options[:progress]
28
+
29
+ # select those that depend on #{gem}
30
+ gem_names_and_dependencies.map do |_, dependencies|
31
+ found = dependencies.select{|d| d.name == gem}
32
+ next if found.empty?
33
+ [_, found]
34
+ end.compact
35
+ end
36
+
37
+ private
38
+
39
+ # dependencies for given gem
40
+ def self.dependencies(spec_tuple, source_uri)
41
+ begin
42
+ fetcher = Gem::SpecFetcher.fetcher
43
+ fetcher.fetch_spec(spec_tuple, URI.parse(source_uri)).dependencies
44
+ rescue Gem::RemoteFetcher::FetchError, Zlib::DataError => e
45
+ $stderr.puts e
46
+ []
47
+ end
48
+ end
49
+
50
+ def self.all_specs_and_sources
51
+ fetcher = Gem::SpecFetcher.fetcher
52
+ all = true
53
+ matching_platform = false
54
+ prerelease = false
55
+ name = Gem::Dependency.new(//i, Gem::Requirement.default)
56
+ specs_and_sources = fetcher.find_matching name, all, matching_platform, prerelease
57
+ uniq_by(specs_and_sources){|a|a.first.first}
58
+ end
59
+
60
+ # get unique elements from an array (last found is used)
61
+ # http://drawohara.com/post/146659159/ruby-enumerable-uniq-by
62
+ def self.uniq_by(array, &block)
63
+ uniq = {}
64
+ array.each_with_index do |val, idx|
65
+ key = block.call(val)
66
+ uniq[key] = [idx, val]
67
+ end
68
+ values = uniq.values
69
+ values.sort!{|a,b| a.first <=> b.first}
70
+ values.map!{|pair| pair.last}
71
+ values
72
+ end
73
+
74
+ def self.with_changed_source(sources)
75
+ sources = [*sources].compact
76
+ if sources.empty?
77
+ yield
78
+ else
79
+ begin
80
+ old = Gem.sources
81
+ Gem.sources = sources
82
+ yield
83
+ ensure
84
+ Gem.sources = old
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems/command_manager'
2
+ require 'rubygems/commands/dependent_command'
3
+ Gem::CommandManager.instance.register_command :dependent
@@ -0,0 +1,56 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
2
+ require 'lib/rubygems/dependent' # normal require does not work once gem is installed, wtf...
3
+
4
+ describe Gem::Dependent do
5
+ before do
6
+ Gem::SpecFetcher.fetcher = nil # reset cache
7
+ end
8
+
9
+ let(:fixture){ YAML.load(File.read('spec/fixtures/gemcutter_specs.yml')) }
10
+ let(:hoe_gems){
11
+ [
12
+ ["7digital", ["hoe"]],
13
+ ["abingo_port", ["hoe"]],
14
+ ["abundance", ["hoe"]],
15
+ ["actionview-data", ["hoe"]],
16
+ ["active_link_to", ["hoe"]],
17
+ ["activemerchant-paymentech-orbital", ["hoe"]],
18
+ ["active_nomad", ["hoe"]],
19
+ ["active_presenter", ["hoe"]],
20
+ ["activerecord-fast-import", ["hoe"]],
21
+ ["activerecord-jdbc-adapter", ["hoe"]]
22
+ ]
23
+ }
24
+
25
+ def simplify(dependencies)
26
+ dependencies.map{|name, deps| [name, deps.map{|d| d.name}] }
27
+ end
28
+
29
+ def stub_source(gem_source = nil)
30
+ gem_source ||= 'http://gemcutter.org'
31
+ Gem::SpecFetcher.fetcher.should_receive(:load_specs).with(URI.parse(gem_source), 'specs').and_return(fixture)
32
+ Gem.sources = [gem_source]
33
+ end
34
+
35
+ it 'finds dependencies for given gem' do
36
+ stub_source
37
+ dependencies = simplify(Gem::Dependent.find('hoe'))
38
+ dependencies.should == hoe_gems
39
+ end
40
+
41
+ it "obeys fetch-limit" do
42
+ stub_source
43
+ dependencies = simplify(Gem::Dependent.find('hoe', :fetch_limit => 100))
44
+ dependencies.should == hoe_gems.first(4)
45
+ end
46
+
47
+ it "can use given source" do
48
+ source = 'http://rubygems.org'
49
+ stub_source(source)
50
+ Gem::Dependent.find('hoe', :source => source)
51
+ end
52
+
53
+ it "has a VERSION" do
54
+ Gem::Dependent::VERSION.should =~ /^\d+\.\d+\.\d+$/
55
+ end
56
+ end