gem-prune 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 David Dollar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ = gem-prune
2
+
3
+ Adds a 'prune' command to rubygems to help keep things tidy. Traverses your
4
+ dependency tree, finds the leaves, and asks you whether or not you want to
5
+ keep them. Remembers which gems you want to keep in ~/.gem-prune
6
+
7
+ Installation
8
+
9
+ $ gem install ddollar-gem-prune
10
+
11
+ Usage
12
+
13
+ $ sudo gem prune
14
+
15
+ Example
16
+
17
+ json_pure (1.1.6)
18
+ [k] keep this gem
19
+ [u] uninstall this gem
20
+ [s] skip (default)
21
+ >
22
+
23
+ == Copyright
24
+
25
+ Copyright (c) 2009 David Dollar. See LICENSE for details.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ Dir[File.join(File.dirname(__FILE__), '..', 'lib', '**', '*.rb')].each do |file|
6
+ require file
7
+ end
8
+
9
+ prune = Gem::Commands::PruneCommand.new
10
+ prune.execute
@@ -0,0 +1,134 @@
1
+ require 'rubygems/command'
2
+ require 'rubygems/command_manager'
3
+ require 'rubygems/uninstaller'
4
+ require 'gem/prune/gem'
5
+ require 'gem/prune/version'
6
+
7
+ class Gem::Commands::PruneCommand < Gem::Command
8
+
9
+ def initialize
10
+ super 'prune', 'Identify and remove old gems'
11
+ end
12
+
13
+ def execute
14
+ return if leaves.empty?
15
+ leaves.each do |name, versions|
16
+ leaf_versions = versions.map { |v| v.version }.join(', ')
17
+ kept_versions = (gems[name].versions - versions).map { |v| v.version }.join(', ')
18
+ begin
19
+ question = "#{name} (#{leaf_versions}) keeping (#{kept_versions})\n"
20
+ question << " [k] keep this gem\n"
21
+ question << " [u] uninstall this gem\n"
22
+ question << " [s] skip (default)\n"
23
+ question << "> "
24
+ print question
25
+ case $stdin.gets.chomp
26
+ when 'k' then keep_gem(name)
27
+ when 'u' then uninstall(name)
28
+ end
29
+ rescue Gem::FilePermissionError
30
+ puts 'Unable to uninstall. Try sudo?'
31
+ next
32
+ end
33
+ end
34
+ rescue Exception => ex
35
+ puts "Unhandled Exception: #{ex.message}"
36
+ end
37
+
38
+ ## commands ##################################################################
39
+
40
+ def keep_gem(name)
41
+ kept = load_kept_gems
42
+ kept << name
43
+ save_kept_gems(kept.uniq)
44
+ end
45
+
46
+ def uninstall(name)
47
+ leaves[name].each do |version|
48
+ uninstaller(name, version.version).uninstall
49
+ end
50
+ end
51
+
52
+ private ######################################################################
53
+
54
+ def gems
55
+ @gems ||= begin
56
+ gems = Gem.source_index.gems.values.inject({}) do |memo, raw|
57
+ gem = memo[raw.name] || Gem::Prune::Gem.new(raw.name)
58
+ gem.versions << Gem::Prune::Version.new(gem, raw)
59
+ memo.update(raw.name => gem)
60
+ end
61
+ discover_relationships(gems)
62
+ gems
63
+ end
64
+ end
65
+
66
+ def discover_relationships(gems)
67
+ gems.values.each { |gem| gem.clear_relationships }
68
+
69
+ gems.each do |name, gem|
70
+ gem.versions.each do |version|
71
+ version.raw.dependencies.each do |dep|
72
+ next if ignore_dependency(dep)
73
+ next unless gems[dep.name]
74
+ match = gems[dep.name].versions.sort.reverse.detect { |v| dep =~ v }
75
+ next unless match
76
+ match.dependants << version
77
+ version.dependencies << match
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def leaves
84
+ @leaves ||= gems.keys.inject({}) do |memo, name|
85
+ leaves = gems[name].versions.select do |version|
86
+ version.dependants.length.zero? && !ignore_version(version)
87
+ end
88
+ memo[name] = leaves unless leaves.length.zero?
89
+ memo
90
+ end
91
+ end
92
+
93
+ def ignore_version(version)
94
+ name = version.name
95
+ highest_version = gems[name].versions.sort.last
96
+ needed_versions = gems[name].versions.select { |v| v.dependants.length > 0 }
97
+ ignored_versions = gems[name].versions.select { |v| ignore_specification(v.raw) }
98
+ return true if ignore_specification(version.raw)
99
+ return true if load_kept_gems.include?(name) && version == highest_version
100
+ return true if needed_versions.length > 0 && version == highest_version
101
+ return true if ignored_versions.length > 0 && version == highest_version
102
+ false
103
+ end
104
+
105
+ def ignore_specification(specification)
106
+ return true if specification.loaded_from =~ /\/System\/Library/
107
+ false
108
+ end
109
+
110
+ def ignore_dependency(dependency)
111
+ false
112
+ end
113
+
114
+ def uninstaller(name, version)
115
+ Gem::Uninstaller.new(name, :version => version, :executables => true)
116
+ end
117
+
118
+ def load_kept_gems
119
+ YAML::load_file(settings_filename)['keep']
120
+ rescue
121
+ []
122
+ end
123
+
124
+ def save_kept_gems(gems)
125
+ File.open(settings_filename, 'w') do |file|
126
+ file.puts({ 'keep' => gems.sort }.to_yaml)
127
+ end
128
+ end
129
+
130
+ def settings_filename
131
+ File.expand_path('~/.gem-prune')
132
+ end
133
+
134
+ end
@@ -0,0 +1,15 @@
1
+ module Gem; module Prune; class Gem
2
+
3
+ attr_reader :name
4
+ attr_reader :versions
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ @versions = []
9
+ end
10
+
11
+ def clear_relationships
12
+ versions.each { |v| v.clear_relationships }
13
+ end
14
+
15
+ end; end; end
@@ -0,0 +1,41 @@
1
+ module Gem; module Prune; class Version
2
+
3
+ attr_reader :gem
4
+ attr_reader :raw
5
+ attr_reader :dependants
6
+ attr_reader :dependencies
7
+
8
+ def initialize(gem, raw)
9
+ @gem = gem
10
+ @raw = raw
11
+
12
+ clear_relationships
13
+ end
14
+
15
+ def inspect
16
+ pretty = %{<Gem::Prune::Version }
17
+ pretty << %{@name="#{name}" }
18
+ pretty << %{@version="#{version}" }
19
+ pretty << %{@dependants="#{dependants.map { |d| "#{d.name}-#{d.version}" }.join(' ') }" }
20
+ pretty << %{@dependencies="#{dependencies.map { |d| "#{d.name}-#{d.version}" }.join(' ') }"}
21
+ pretty << %{>}
22
+ end
23
+
24
+ def name
25
+ raw.name
26
+ end
27
+
28
+ def version
29
+ raw.version
30
+ end
31
+
32
+ def clear_relationships
33
+ @dependants = []
34
+ @dependencies = []
35
+ end
36
+
37
+ def <=>(other)
38
+ version <=> other.version
39
+ end
40
+
41
+ end; end; end
@@ -0,0 +1,3 @@
1
+ require 'gem/commands/prune_command'
2
+
3
+ Gem::CommandManager.instance.register_command :prune
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "GemPrune" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ require 'gem-prune'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gem-prune
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.4.1
5
+ platform: ruby
6
+ authors:
7
+ - David Dollar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-18 00:00:00 -04:00
13
+ default_executable: gem-prune
14
+ dependencies: []
15
+
16
+ description:
17
+ email: <ddollar@gmail.com>
18
+ executables:
19
+ - gem-prune
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - lib/gem/commands/prune_command.rb
27
+ - lib/gem/prune/gem.rb
28
+ - lib/gem/prune/version.rb
29
+ - lib/rubygems_plugin.rb
30
+ - LICENSE
31
+ - README.rdoc
32
+ has_rdoc: true
33
+ homepage: http://github.com/ddollar/gem-prune
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
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:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Identify and remove old Rubygems
60
+ test_files:
61
+ - spec/gem-prune_spec.rb
62
+ - spec/spec_helper.rb