gem-prune 1.4.1

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