aboutsummaryrefslogtreecommitdiffstats
path: root/tool/outdate-bundled-gems.rb
blob: bf6b26870010c818b9ea0b20c4c32326dd2f8214 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/ruby
require 'fileutils'
require 'rubygems'

fu = FileUtils::Verbose
until ARGV.empty?
  case ARGV.first
  when '--'
    ARGV.shift
    break
  when '-n', '--dryrun'
    fu = FileUtils::DryRun
  when /\A--make=/
    # just to run when `make -n`
  when /\A--mflags=(.*)/
    fu = FileUtils::DryRun if /\A-\S*n/ =~ $1
  when /\A-/
    raise "#{$0}: unknown option: #{ARGV.first}"
  else
    break
  end
  ARGV.shift
end

class Removal
  def initialize(base = nil)
    @base = (File.join(base, "/") if base)
    @remove = {}
  end

  def prefixed(name)
    @base ? File.join(@base, name) : name
  end

  def stripped(name)
    if @base && name.start_with?(@base)
      name[@base.size..-1]
    else
      name
    end
  end

  def slash(name)
    name.sub(%r[[^/]\K\z], '/')
  end

  def exist?(name)
    !@remove.fetch(name) {|k| @remove[k] = !File.exist?(prefixed(name))}
  end
  def directory?(name)
    !@remove.fetch(slash(name)) {|k| @remove[k] = !File.directory?(prefixed(name))}
  end

  def unlink(name)
    @remove[stripped(name)] = :rm_f
  end
  def rmdir(name)
    @remove[slash(stripped(name))] = :rm_rf
  end

  def glob(pattern, *rest)
    Dir.glob(prefixed(pattern), *rest) {|n|
      yield stripped(n)
    }
  end

  def each_file
    @remove.each {|k, v| yield prefixed(k) if v == :rm_f}
  end

  def each_directory
    @remove.each {|k, v| yield prefixed(k) if v == :rm_rf}
  end
end

srcdir = Removal.new(ARGV.shift)
curdir = Removal.new

srcdir.glob(".bundle/gems/*/") do |dir|
  unless srcdir.exist?("gems/#{File.basename(dir)}.gem")
    srcdir.rmdir(dir)
  end
end

srcdir.glob(".bundle/specifications/*.gemspec") do |spec|
  unless srcdir.directory?(".bundle/gems/#{File.basename(spec, '.gemspec')}/")
    srcdir.unlink(spec)
  end
end

curdir.glob(".bundle/specifications/*.gemspec") do |spec|
  unless srcdir.directory?(".bundle/gems/#{File.basename(spec, '.gemspec')}")
    curdir.unlink(spec)
  end
end

curdir.glob(".bundle/gems/*/") do |dir|
  base = File.basename(dir)
  unless curdir.exist?(".bundle/specifications/#{base}.gemspec") or
        curdir.exist?("#{dir}/.bundled.#{base}.gemspec")
    curdir.rmdir(dir)
  end
end

platform = Gem::Platform.local.to_s
curdir.glob(".bundle/{extensions,.timestamp}/*/") do |dir|
  unless File.basename(dir) == platform
    curdir.rmdir(dir)
  end
end

baseruby_version = RbConfig::CONFIG['ruby_version'] # This may not have "-static"
curdir.glob(".bundle/{extensions,.timestamp}/#{platform}/*/") do |dir|
  version = File.basename(dir).split('-', 2).first # Remove "-static" if exists
  unless version == baseruby_version
    curdir.rmdir(dir)
  end
end

curdir.glob(".bundle/extensions/#{platform}/#{baseruby_version}/*/") do |dir|
  unless curdir.exist?(".bundle/specifications/#{File.basename(dir)}.gemspec")
    curdir.rmdir(dir)
  end
end

curdir.glob(".bundle/.timestamp/#{platform}/#{baseruby_version}/.*.time") do |stamp|
  unless curdir.directory?(File.join(".bundle", stamp[%r[/\.([^/]+)\.time\z], 1].gsub('.-.', '/')))
    curdir.unlink(stamp)
  end
end

srcdir.each_file {|f| fu.rm_f(f)}
srcdir.each_directory {|d| fu.rm_rf(d)}
curdir.each_file {|f| fu.rm_f(f)}
curdir.each_directory {|d| fu.rm_rf(d)}