gem-dependent 0.1.0

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.
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