52: def execute
53: gem_name = nil
54:
55: specs = if options[:all] then
56: Gem::SourceIndex.from_installed_gems.map do |name, spec|
57: spec
58: end
59: else
60: gem_name = get_one_gem_name
61: Gem::SourceIndex.from_installed_gems.search(gem_name,
62: options[:version])
63: end
64:
65: if specs.empty? then
66: raise Gem::Exception,
67: "Failed to find gem #{gem_name} #{options[:version]}"
68: end
69:
70: install_dir = Gem.dir
71:
72: raise Gem::FilePermissionError.new(install_dir) unless
73: File.writable?(install_dir)
74:
75: say "Restoring gem(s) to pristine condition..."
76:
77: specs.each do |spec|
78: gem = Dir[File.join(Gem.dir, 'cache', "#{spec.full_name}.gem")].first
79:
80: if gem.nil? then
81: alert_error "Cached gem for #{spec.full_name} not found, use `gem install` to restore"
82: next
83: end
84:
85:
86: installer = Gem::Installer.new gem, :wrappers => true
87:
88: gem_file = File.join install_dir, "cache", "#{spec.full_name}.gem"
89:
90: security_policy = nil
91:
92: format = Gem::Format.from_file_by_path gem_file, security_policy
93:
94: target_directory = File.join(install_dir, "gems", format.spec.full_name)
95: target_directory.untaint
96:
97: pristine_files = format.file_entries.collect { |data| data[0]["path"] }
98: file_map = {}
99:
100: format.file_entries.each do |entry, file_data|
101: file_map[entry["path"]] = file_data
102: end
103:
104: Dir.chdir target_directory do
105: deployed_files = Dir.glob(File.join("**", "*")) +
106: Dir.glob(File.join("**", ".*"))
107:
108: pristine_files = pristine_files.map { |f| File.expand_path f }
109: deployed_files = deployed_files.map { |f| File.expand_path f }
110:
111: to_redeploy = (pristine_files - deployed_files)
112: to_redeploy = to_redeploy.map { |path| path.untaint}
113:
114: if to_redeploy.length > 0 then
115: say "Restoring #{to_redeploy.length} file#{to_redeploy.length == 1 ? "" : "s"} to #{spec.full_name}..."
116:
117: to_redeploy.each do |path|
118: say " #{path}"
119: FileUtils.mkdir_p File.dirname(path)
120: File.open(path, "wb") do |out|
121: out.write file_map[path]
122: end
123: end
124: else
125: say "#{spec.full_name} is in pristine condition"
126: end
127: end
128:
129: installer.generate_bin
130: installer.build_extensions
131: end
132: end