dekernel 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/dekernel +28 -0
- data/lib/dekernel.rb +24 -0
- data/lib/dekernel/cernel.rb +104 -0
- data/lib/dekernel/message.rb +74 -0
- data/spec/lib/dekernel/cernel_spec.rb +284 -0
- data/spec/lib/dekernel/message_spec.rb +110 -0
- data/spec/lib/dekernel_spec.rb +57 -0
- data/spec/spec_helper.rb +28 -0
- metadata +75 -0
data/bin/dekernel
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
$options = { dry_run: false, assume_yes: false, kernels_list: nil,
|
5
|
+
all_except: nil, no_confirm: false }
|
6
|
+
OptionParser.new { |opts|
|
7
|
+
opts.banner = "Usage: ./deKernelScript [--dry-run, --assume-yes, --kernels-list=[space separated kernel #'s]"
|
8
|
+
|
9
|
+
opts.on('-s', '--dry-run', 'Dry run with apt-get') do
|
10
|
+
$options[:dry_run] = true
|
11
|
+
end
|
12
|
+
opts.on('-y', '--assume-yes', 'Assume yes with apt-get') do
|
13
|
+
$options[:assume_yes] = true
|
14
|
+
end
|
15
|
+
opts.on('-n', '--no-confirm', "Do not confirm with 'Are you sure?' message") do
|
16
|
+
$options[:no_confirm] = true
|
17
|
+
end
|
18
|
+
opts.on('-x', '--all-except', 'Remove all except the lastest (n) kernels', '=MANDATORY', Integer) do |v|
|
19
|
+
$options[:all_except] = v.to_i
|
20
|
+
end
|
21
|
+
opts.on('-k', '--kernels-list', 'Kernels to remove list', '=MANDATORY') do |v|
|
22
|
+
$options[:kernels_list] = v
|
23
|
+
end
|
24
|
+
}.parse!
|
25
|
+
|
26
|
+
require 'dekernel'
|
27
|
+
|
28
|
+
DeKernel.run
|
data/lib/dekernel.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
class DeKernel
|
2
|
+
require 'dekernel/cernel'
|
3
|
+
require 'dekernel/message'
|
4
|
+
|
5
|
+
def self.run
|
6
|
+
original_free_space = Cernel.get_free_disk_space
|
7
|
+
Kernel.system "clear"
|
8
|
+
if $options[:dry_run]
|
9
|
+
$stdout.puts "\n" + " THIS IS A DRY-RUN!, apt-get will only pretend." + "\n" + "\n"
|
10
|
+
end
|
11
|
+
$stdout.puts "It's generally recommended to leave at least " +
|
12
|
+
"three of your latest kernels installed." + "\n" + "\n"
|
13
|
+
if $options[:all_except] != nil
|
14
|
+
Cernel.purge_packages_from_a_list_of_kernels(Cernel.find_all_except_latest($options[:all_except]))
|
15
|
+
elsif $options[:kernels_list] != nil
|
16
|
+
Cernel.purge_packages_from_a_list_of_kernels(Cernel.safe_ified_kernels_list)
|
17
|
+
else
|
18
|
+
Cernel.purge_packages_from_a_list_of_kernels(Cernel.ask_which_to_remove)
|
19
|
+
end
|
20
|
+
ensure
|
21
|
+
$stdout.puts Message.other_kernels
|
22
|
+
$stdout.puts "#{Cernel.get_free_disk_space - original_free_space} megabytes of disk space were freed."
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
class Cernel
|
2
|
+
class << self
|
3
|
+
def find_kernels
|
4
|
+
all_kernels = find_all_kernels
|
5
|
+
installed_kernels = find_installed_kernels(all_kernels)
|
6
|
+
{ all: all_kernels, installed: installed_kernels }
|
7
|
+
end
|
8
|
+
|
9
|
+
def ask_which_to_remove
|
10
|
+
installed_kernels = find_kernels[:installed]
|
11
|
+
$stdout.puts Message.installed_kernels(installed_kernels)
|
12
|
+
Kernel.exit if installed_kernels.length == 0
|
13
|
+
kernels_to_remove = create_kernels_to_remove_list(installed_kernels)
|
14
|
+
end
|
15
|
+
|
16
|
+
def purge_packages_from_a_list_of_kernels(kernels_to_remove)
|
17
|
+
($stderr.puts "\n" + "No kernels selected!" ; Kernel.exit) unless kernels_to_remove.length > 0
|
18
|
+
confirm_removals(kernels_to_remove) unless $options[:no_confirm]
|
19
|
+
packages_list = find_kernel_packages(kernels_to_remove)
|
20
|
+
IO.send(:popen, "sudo apt-get purge #{apt_options} #{packages_list.join("\s")} 1>&2") { |p| p.each { |f| $stdout.puts f } }
|
21
|
+
if $?.exitstatus != 0
|
22
|
+
$stdout.puts Message.purge_packages_failure($?)
|
23
|
+
else
|
24
|
+
$stdout.puts Message.purge_packages_success(kernels_to_remove)
|
25
|
+
Kernel.system "sudo apt-get clean" unless $options[:dry_run]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_free_disk_space
|
30
|
+
Kernel.send(:`, "df -BM /boot").split[10].to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_all_except_latest(number)
|
34
|
+
kernels = find_kernels
|
35
|
+
sort_properly(kernels[:installed]).rotate(-number).drop(number)
|
36
|
+
end
|
37
|
+
|
38
|
+
def safe_ified_kernels_list
|
39
|
+
options = $options[:kernels_list].split(" ").reject { |kernel| kernel =~ (/[a-z]/i) }
|
40
|
+
options = options.reject { |kernel| kernel =~ (/[0-9]{3,}/i) }
|
41
|
+
options.select { |kernel| kernel =~ kernel_regex }
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
private
|
46
|
+
def find_all_kernels
|
47
|
+
Kernel.send(:`, "ls /boot").each_line.grep(/vmlinuz/).collect { |l|
|
48
|
+
l.match(kernel_regex).to_s
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def kernel_regex
|
53
|
+
/[0-9]\.[0-9]{1,2}\.[0-9]{1,2}-[0-9]{1,2}/
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_installed_kernels(all_kernels)
|
57
|
+
all_kernels.select { |kernel|
|
58
|
+
Kernel.send(:system, "dpkg-query -f '${Package}\n' -W *#{kernel}* >/dev/null 2>&1")
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_kernels_to_remove_list(installed_kernels)
|
63
|
+
installed_kernels.select { |kernel|
|
64
|
+
$stdout.print "Do you want to remove the #{kernel} kernel [y/N/yes/NO/?]"
|
65
|
+
next unless !!ARGF.first.strip.match(/^y$|^yes$/i)
|
66
|
+
$stdout.puts "Marking #{kernel} for removal" ; true
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def find_kernel_packages(kernels_to_remove)
|
71
|
+
packages = kernels_to_remove.map { |kernel|
|
72
|
+
Kernel.send(:`, "dpkg-query -f '${Package}\n' -W *#{kernel}*").split("\n")
|
73
|
+
}.flatten
|
74
|
+
if packages.empty?
|
75
|
+
$stderr.puts "ERROR: No packages to remove." ; Kernel.exit
|
76
|
+
else
|
77
|
+
$stdout.puts "Packages are being uninstalled, please stand by..."
|
78
|
+
end ; packages
|
79
|
+
end
|
80
|
+
|
81
|
+
def confirm_removals(kernels_to_remove)
|
82
|
+
all_kernels = find_kernels
|
83
|
+
installed_kernels = all_kernels[:installed]
|
84
|
+
Kernel.system "clear"
|
85
|
+
$stdout.puts Message.ask_to_confirm_kernels_to_remove(kernels_to_remove, installed_kernels)
|
86
|
+
($stderr.puts "Canceled!" ; Kernel.exit) unless !!ARGF.first.strip.match(/^y$|^yes$/i)
|
87
|
+
kernels_to_remove
|
88
|
+
end
|
89
|
+
|
90
|
+
def sort_properly(kernels)
|
91
|
+
kernels.sort_by { |kernel_string|
|
92
|
+
split = kernel_string.split(/-/)
|
93
|
+
[split[0], "%02d" % split[1]].join('-')
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def apt_options
|
98
|
+
{ y: $options[:assume_yes], s: $options[:dry_run] }.collect { |k, v|
|
99
|
+
if v == true ; "-#{k}" ; end
|
100
|
+
}.join(' ').strip
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class Message
|
2
|
+
class << self
|
3
|
+
## Every method in this class returns a String object
|
4
|
+
|
5
|
+
def installed_kernels(installed_kernels)
|
6
|
+
[kernel_count(installed_kernels),
|
7
|
+
(installed_kernels.collect { |k| " #{k} " })].flatten.push("", "").join("\n")
|
8
|
+
end
|
9
|
+
|
10
|
+
def other_kernels
|
11
|
+
kernels = Cernel.find_kernels
|
12
|
+
if (kernels[:all] - kernels[:installed]).length > 0
|
13
|
+
["",
|
14
|
+
"### NOTE: You have kernels in your /boot directory " +
|
15
|
+
"that have no corresponding packages installed.",
|
16
|
+
"### If you know you don't want those kernels, " +
|
17
|
+
"you may want to remove them.",
|
18
|
+
"### You can list and remove them with the following commands:",
|
19
|
+
list_and_remove_commands(kernels[:all] - kernels[:installed]),
|
20
|
+
"", ""].join("\n")
|
21
|
+
end or String.new
|
22
|
+
end
|
23
|
+
|
24
|
+
[:success, :failure].each { |exit_status|
|
25
|
+
define_method "purge_packages_#{exit_status}" do |message|
|
26
|
+
if exit_status == :success
|
27
|
+
["",
|
28
|
+
"Successfully removed the kernel packages for: #{message.join(', ')}",
|
29
|
+
"",
|
30
|
+
"### NOTE: Usually apt-get will update your bootloader automatically,",
|
31
|
+
"### but if you have any trouble you may need to update it manually.",
|
32
|
+
"### (i.e. `sudo update-grub2` if you are using grub2)"]
|
33
|
+
else
|
34
|
+
["", "ERROR: apt-get purge failed with \"#{message}\""]
|
35
|
+
end.join("\n")
|
36
|
+
end
|
37
|
+
}
|
38
|
+
|
39
|
+
def ask_to_confirm_kernels_to_remove(kernels_to_remove, installed_kernels)
|
40
|
+
header_message = kernels_to_remove.length > 1 \
|
41
|
+
? "The #{kernels_to_remove.length} kernels marked with asterisks will be apt-get purged:" \
|
42
|
+
: "The kernel marked with asterisks will be apt-get purged:"
|
43
|
+
marked_up_kernels_list = installed_kernels.collect { |kernel|
|
44
|
+
kernels_to_remove.include?(kernel) ? "**#{kernel}**" : " #{kernel} "
|
45
|
+
}
|
46
|
+
[header_message, marked_up_kernels_list, "",
|
47
|
+
"Are you sure you want to continue [y/N/yes/NO/?]"].join("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
{ "list" => "ls -ahl", "remove" => "rm -f " }.each { |name, command|
|
52
|
+
define_method "#{name}_command" do |other_kernels|
|
53
|
+
command = other_kernels.collect { |kernel| "sudo #{command} /boot/*-#{kernel}*" }.join(" && ")
|
54
|
+
"### `%s`" % command
|
55
|
+
end
|
56
|
+
}
|
57
|
+
|
58
|
+
def list_and_remove_commands(other_kernels)
|
59
|
+
[list_command(other_kernels), remove_command(other_kernels)].join("\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
def kernel_count(installed_kernels)
|
63
|
+
case installed_kernels.length
|
64
|
+
when 0
|
65
|
+
"ERROR: No kernels found in the /boot directory!"
|
66
|
+
when 1
|
67
|
+
"Only one kernel found!"
|
68
|
+
when 2..(1.0/0.0)
|
69
|
+
"Found #{installed_kernels.length} kernels installed:"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Cernel' do
|
4
|
+
before :each do
|
5
|
+
$stdout.stub!(:puts)
|
6
|
+
$stdout.stub!(:print)
|
7
|
+
$stderr.stub!(:puts)
|
8
|
+
Kernel.stub!(:system)
|
9
|
+
end
|
10
|
+
context "#find_kernels" do
|
11
|
+
it "finds all kernels" do
|
12
|
+
Cernel.stub!(:find_all_kernels).and_return(@all_kernels)
|
13
|
+
kernels = Cernel.find_kernels
|
14
|
+
expect(kernels[:all]).to eq @all_kernels
|
15
|
+
end
|
16
|
+
|
17
|
+
it "finds installed kernels" do
|
18
|
+
Cernel.stub!(:find_installed_kernels).and_return(@installed_kernels)
|
19
|
+
kernels = Cernel.find_kernels
|
20
|
+
expect(kernels[:installed]).to eq @installed_kernels
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "#ask_which_to_remove" do
|
25
|
+
it "raises SystemExit if installed_kernels.length == 0" do
|
26
|
+
Cernel.stub!(:find_kernels).and_return({ installed: [] })
|
27
|
+
expect(lambda { Cernel.ask_which_to_remove }).to raise_error SystemExit
|
28
|
+
end
|
29
|
+
|
30
|
+
it "prints each one and adds to list" do
|
31
|
+
Cernel.stub!(:find_installed_kernels).and_return(@installed_kernels)
|
32
|
+
ARGF.stub!(:first).and_return("y", "n", "y")
|
33
|
+
|
34
|
+
expect(Cernel.ask_which_to_remove.to_s).to match(/#{@remove_kernels.to_s}/)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "calls 'Message.installed_kernels(installed_kernels)'" do
|
38
|
+
Kernel.stub!(:exit)
|
39
|
+
Cernel.stub!(:find_kernels).and_return(@kernels_hash)
|
40
|
+
Message.should_receive(:installed_kernels).with(@installed_kernels)
|
41
|
+
ARGF.stub!(:first).and_return("y")
|
42
|
+
|
43
|
+
Cernel.ask_which_to_remove
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "#purge_packages_from_a_list_of_kernels(kernels_to_remove)" do
|
48
|
+
before :each do
|
49
|
+
IO.stub!(:popen)
|
50
|
+
Message.stub!(:purge_packages_success)
|
51
|
+
Message.stub!(:purge_packages_failure)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "calls confirm_removals with $options[:no_confirm] = false (default)" do
|
55
|
+
Cernel.stub!(:find_kernel_packages).and_return(@remove_packages)
|
56
|
+
Cernel.should_receive(:confirm_removals).with(@remove_kernels)
|
57
|
+
|
58
|
+
Cernel.purge_packages_from_a_list_of_kernels(@remove_kernels)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "does not call confirm_removals with $options[:no_confirm] = true" do
|
62
|
+
$options[:no_confirm] = true
|
63
|
+
Cernel.stub!(:find_kernel_packages).and_return(@remove_packages)
|
64
|
+
Cernel.should_not_receive(:confirm_removals).with(@remove_kernels)
|
65
|
+
|
66
|
+
Cernel.purge_packages_from_a_list_of_kernels(@remove_kernels)
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when kernels_to_remove.length is 0" do
|
70
|
+
it "raises SystemExit" do
|
71
|
+
expect(lambda do
|
72
|
+
Cernel.purge_packages_from_a_list_of_kernels([])
|
73
|
+
end).to raise_error SystemExit
|
74
|
+
end
|
75
|
+
|
76
|
+
it "prints 'no kernels selected' message" do
|
77
|
+
Kernel.stub!(:exit)
|
78
|
+
$stderr.should_receive(:puts).with("\nNo kernels selected!")
|
79
|
+
|
80
|
+
Cernel.purge_packages_from_a_list_of_kernels([])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
it "prints 'no packages error' message" do
|
86
|
+
Kernel.stub!(:exit)
|
87
|
+
$stderr.should_receive(:puts).with("ERROR: No packages to remove.")
|
88
|
+
Cernel.purge_packages_from_a_list_of_kernels([])
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when kernels_to_remove.length is > 0" do
|
92
|
+
context "when packages found" do
|
93
|
+
before :each do
|
94
|
+
Cernel.stub!(:confirm_removals).and_return(@remove_kernels)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "prints 'packages being uninstalled' message" do
|
98
|
+
Kernel.stub!(:`).with("dpkg-query -f '${Package}\n' -W *#{@installed_kernels.first}*").
|
99
|
+
and_return("package1 package2")
|
100
|
+
$stdout.should_receive(:puts).with("Packages are being uninstalled, please stand by...")
|
101
|
+
|
102
|
+
Cernel.purge_packages_from_a_list_of_kernels(@installed_kernels.first(1))
|
103
|
+
end
|
104
|
+
|
105
|
+
it "runs `apt-get purge` command with no options" do
|
106
|
+
IO.should_receive(:popen).with("sudo apt-get purge package1 package2 1>&2")
|
107
|
+
Cernel.stub!(:find_kernel_packages).and_return(["package1", "package2"])
|
108
|
+
|
109
|
+
Cernel.purge_packages_from_a_list_of_kernels(@installed_kernels.first(1))
|
110
|
+
end
|
111
|
+
|
112
|
+
it "does not run 'apt-get clean' command if $options[:dry_run] == true" do
|
113
|
+
$options[:dry_run] = true
|
114
|
+
$?.stub!(:exitstatus).and_return(0)
|
115
|
+
IO.should_receive(:popen).with("sudo apt-get purge -s package1 package2 1>&2")
|
116
|
+
Cernel.stub!(:find_kernel_packages).and_return(["package1", "package2"])
|
117
|
+
Kernel.should_not_receive(:system).with("sudo apt-get clean")
|
118
|
+
|
119
|
+
Cernel.purge_packages_from_a_list_of_kernels(@installed_kernels.first(1))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "#get_free_disk_space" do
|
126
|
+
it "gets available disk space" do
|
127
|
+
Kernel.should_receive(:`).with("df -BM /boot").
|
128
|
+
and_return("Filesystem 1M-blocks Used Available Use% Mounted on\n/dev/sdc3 46935M 9115M 35437M 21% /\n")
|
129
|
+
|
130
|
+
Cernel.get_free_disk_space
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "#find_all_except_latest(number)" do
|
135
|
+
it "should find all except latest (number) kernels" do
|
136
|
+
Cernel.stub!(:find_kernels).and_return(@kernels_hash)
|
137
|
+
expect(Cernel.send(:find_all_except_latest, 1)).to eq @all_except_latest_one
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
### private methods, test them or not?
|
143
|
+
|
144
|
+
context "#find_all_kernels" do
|
145
|
+
before :each do
|
146
|
+
Kernel.should_receive(:`).with("ls /boot").
|
147
|
+
and_return("vmlinuz-2.28.10-38-generic\nvmlinuz-3.2.0-39-generic\nvmlinuz-3.2.0-40-generic\n")
|
148
|
+
end
|
149
|
+
|
150
|
+
it "returns an array" do
|
151
|
+
expect(Cernel.send(:find_all_kernels)).to be_a_kind_of(Array)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "returns greped kernel numbers" do
|
155
|
+
expect(Cernel.send(:find_all_kernels)).to eq ["2.28.10-38", "3.2.0-39", "3.2.0-40"]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "#find_installed_kernels(all_kernels)" do
|
160
|
+
it "returns an array" do
|
161
|
+
expect(Cernel.send(:find_installed_kernels, @all_kernels)).to be_a_kind_of(Array)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "calls dpkg command for each kernel" do
|
165
|
+
@all_kernels.each do |kernel|
|
166
|
+
Kernel.stub!(:`).with("dpkg-query -f '${Package}\n' -W *#{kernel}* >/dev/null 2>&1")
|
167
|
+
Kernel.should_receive(:system).with("dpkg-query -f '${Package}\n' -W *#{kernel}* >/dev/null 2>&1").
|
168
|
+
and_return("linux-headers-#{kernel}\nlinux-headers-#{kernel}-generic\nlinux-image-#{kernel}-generic\n")
|
169
|
+
end
|
170
|
+
Cernel.send(:find_installed_kernels, @all_kernels)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "returns only kernels that have installed packages" do
|
174
|
+
{ "true" => @installed_kernels, "false" => @other_kernels }.each do |value, kernels|
|
175
|
+
kernels.each do |kernel|
|
176
|
+
Kernel.stub!(:system).
|
177
|
+
with("dpkg-query -f '${Package}\n' -W *#{kernel}* >/dev/null 2>&1").
|
178
|
+
and_return(!!value.match(/true/))
|
179
|
+
end
|
180
|
+
end
|
181
|
+
expect(Cernel.send(:find_installed_kernels, @all_kernels)).to eq @installed_kernels
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "#create_kernels_to_remove_list(installed_kernels)" do
|
186
|
+
it "returns an array" do
|
187
|
+
ARGF.should_receive(:first).exactly(@installed_kernels.length).times.and_return('yes')
|
188
|
+
expect(Cernel.send(:create_kernels_to_remove_list, @installed_kernels)).to be_a_kind_of(Array)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "returns only the kernels selected" do
|
192
|
+
ARGF.should_receive(:first).exactly(@installed_kernels.length).times.and_return('yes', 'no', 'no')
|
193
|
+
expect(Cernel.send(:create_kernels_to_remove_list, @installed_kernels)).to eq @installed_kernels.first(1)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context "#find_kernel_packages(kernels_to_remove)" do
|
198
|
+
before :each do
|
199
|
+
@remove_kernels.each do |kernel|
|
200
|
+
Kernel.should_receive(:`).exactly(1).times.with("dpkg-query -f '${Package}\n' -W *#{kernel}*").
|
201
|
+
and_return(@remove_packages.join("\n"))
|
202
|
+
end
|
203
|
+
(@all_kernels - @remove_kernels).each do |kernel|
|
204
|
+
Kernel.should_not_receive(:system).with("dpkg-query -f '${Package}\n' -W *#{kernel}*")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
it "returns an array" do
|
209
|
+
expect(Cernel.send(:find_kernel_packages, @remove_kernels)).to be_a_kind_of(Array)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "returns only packages from the kernels_to_remove" do
|
213
|
+
# why do i have to use 'uniq' right here? without 'uniq' it returns a doubled array.
|
214
|
+
#expect(Cernel.send(:find_kernel_packages, @remove_kernels)).to eq @remove_packages
|
215
|
+
expect(Cernel.send(:find_kernel_packages, @remove_kernels).uniq).to eq @remove_packages
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context "#confirm_removals(kernels_to_remove, installed_kernels)" do
|
220
|
+
before :each do
|
221
|
+
Cernel.stub!(:find_kernels).and_return(@kernels_hash)
|
222
|
+
ARGF.should_receive(:first).exactly(1).times.and_return('no')
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when confirmation not met" do
|
226
|
+
it "raises system exit" do
|
227
|
+
expect(lambda do
|
228
|
+
Cernel.send(:confirm_removals, @remove_kernels)
|
229
|
+
end).to raise_error SystemExit
|
230
|
+
end
|
231
|
+
|
232
|
+
it "prints 'canceled' message" do
|
233
|
+
Kernel.stub!(:exit)
|
234
|
+
|
235
|
+
$stderr.should_receive(:puts).with("Canceled!")
|
236
|
+
Cernel.send(:confirm_removals, @remove_kernels)
|
237
|
+
end
|
238
|
+
|
239
|
+
it "returns kernels_to_remove" do
|
240
|
+
Kernel.stub!(:exit)
|
241
|
+
|
242
|
+
expect(Cernel.send(:confirm_removals, @remove_kernels)).to eq @remove_kernels
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context "#sort_properly(kernels)" do
|
248
|
+
it "pads dash-number" do
|
249
|
+
unsorted = ["2.23.10-1", "3.2.0-8", "2.23.1-4", "3.2.0-11", "2.3.1-10", "2.23.1-34"]
|
250
|
+
sorted = ["2.23.1-4", "2.23.1-34", "2.23.10-1", "2.3.1-10", "3.2.0-8", "3.2.0-11"]
|
251
|
+
|
252
|
+
expect(Cernel.send(:sort_properly, unsorted)).to eq sorted
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "#apt_options" do
|
257
|
+
it "returns a string of the options" do
|
258
|
+
$options[:assume_yes] = false
|
259
|
+
$options[:dry_run] = false
|
260
|
+
expect(Cernel.send(:apt_options)).to eq ""
|
261
|
+
|
262
|
+
$options[:assume_yes] = true
|
263
|
+
$options[:dry_run] = false
|
264
|
+
expect(Cernel.send(:apt_options)).to eq "-y"
|
265
|
+
|
266
|
+
$options[:assume_yes] = false
|
267
|
+
$options[:dry_run] = true
|
268
|
+
expect(Cernel.send(:apt_options)).to eq "-s"
|
269
|
+
|
270
|
+
$options[:assume_yes] = true
|
271
|
+
$options[:dry_run] = true
|
272
|
+
expect(Cernel.send(:apt_options)).to eq "-y -s"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context "#safe_ified_kernels_list" do
|
277
|
+
it "removes entries with letters" do
|
278
|
+
$options[:kernels_list] = "3.2.r-12 3.2.0-11 3.324.43-32 343 3.2.0-123"
|
279
|
+
|
280
|
+
expect(Cernel.send("safe_ified_kernels_list")).to eq ["3.2.0-11"]
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Message' do
|
4
|
+
context "#installed_kernels(installed_kernels)" do
|
5
|
+
context "when installed_kernels = 0" do
|
6
|
+
it "returns 'no kernels found error' message" do
|
7
|
+
expect(Message.installed_kernels([])).
|
8
|
+
to match "ERROR: No kernels found in the /boot directory!"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when installed_kernels = 1" do
|
13
|
+
it "returns 'only one kernel found' message" do
|
14
|
+
expect(Message.installed_kernels(@installed_kernels.last(1))).
|
15
|
+
to match "Only one kernel found!"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when installed_kernels > 1" do
|
20
|
+
it "returns 'multiple kernels found' message" do
|
21
|
+
expect(Message.installed_kernels(@installed_kernels)).
|
22
|
+
to match "Found #{@installed_kernels.length} kernels installed:"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns kernels as a string" do
|
27
|
+
expect(Message.installed_kernels(@installed_kernels)).
|
28
|
+
to match ["Found #{@installed_kernels.length} kernels installed:"].
|
29
|
+
concat(@installed_kernels.collect { |k| " #{k} " }).join("\n")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "#other_kernels" do
|
34
|
+
context "when other_kernels.length is greater than 0" do
|
35
|
+
it "returns 'you have other kernels' message" do
|
36
|
+
Cernel.stub!(:find_kernels).and_return(@kernels_hash)
|
37
|
+
message = "### NOTE: You have kernels in your /boot directory " +
|
38
|
+
"that have no corresponding packages installed." + "\n"
|
39
|
+
"### If you know you don't want those kernels, " +
|
40
|
+
"you may want to remove them."
|
41
|
+
|
42
|
+
expect(Message.other_kernels).to match message
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns list and remove commands" do
|
46
|
+
Cernel.stub!(:find_kernels).
|
47
|
+
and_return(@kernels_hash)
|
48
|
+
|
49
|
+
[@other_kernels.first, "sudo ls -ahl ", "sudo rm -f "].each do |string|
|
50
|
+
expect(Message.other_kernels).to match string
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns nothing if other_kernels.length == 0" do
|
56
|
+
Cernel.stub!(:find_kernels).and_return({ :all => @all_kernels, :installed => @all_kernels })
|
57
|
+
expect(Message.other_kernels).to be_empty
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "#purge_packages_success(kernels_to_remove)" do
|
62
|
+
it "returns successful purge message" do
|
63
|
+
string = [
|
64
|
+
"Successfully removed the kernel packages for: #{@all_kernels.drop(2).join(', ')}",
|
65
|
+
"",
|
66
|
+
"### NOTE: Usually apt-get will update your bootloader automatically,",
|
67
|
+
"### but if you have any trouble you may need to update it manually."].join("\n")
|
68
|
+
expect(Message.purge_packages_success(@all_kernels.drop(2))).to match string
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "#purge_packages_failure(exit_code)" do
|
73
|
+
it "returns failed purge message" do
|
74
|
+
string = 'ERROR: apt-get purge failed with \"12345\"'
|
75
|
+
expect(Message.purge_packages_failure("12345")).to match string
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "#ask_to_confirm_kernels_to_remove(kernels_to_remove, installed_kernels)" do
|
80
|
+
it "returns 'multiple kernels message' when multiple kernels" do
|
81
|
+
output = Message.ask_to_confirm_kernels_to_remove(@installed_kernels.drop(1), @installed_kernels)
|
82
|
+
count = @installed_kernels.drop(1).length
|
83
|
+
|
84
|
+
expect(output).to match "The #{count} kernels marked with asterisks will be apt-get purged:"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "returns 'singular kernel message' when only one kernel" do
|
88
|
+
output = Message.ask_to_confirm_kernels_to_remove(@installed_kernels.first(1),
|
89
|
+
@installed_kernels)
|
90
|
+
|
91
|
+
["The kernel marked with asterisks will be apt-get purged:",
|
92
|
+
"Are you sure you want to continue "].each do |string|
|
93
|
+
expect(output).to match string
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "responds to purge_packages_success and purge_packages_failure methods" do
|
99
|
+
["success", "failure"].each do |boolean|
|
100
|
+
expect(Message).to respond_to("purge_packages_#{boolean}")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "responds to list_command and remove_command methods" do
|
105
|
+
["list", "remove"].each do |name|
|
106
|
+
expect(Message).to respond_to("#{name}_command")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'deKernel' do
|
4
|
+
before :each do
|
5
|
+
$stdout.stub!(:puts)
|
6
|
+
Message.stub!(:other_kernels)
|
7
|
+
Kernel.stub!(:system).with("clear")
|
8
|
+
Cernel.stub!(:get_free_disk_space).and_return(12345)
|
9
|
+
Cernel.stub!(:ask_which_to_remove)
|
10
|
+
Cernel.stub!(:purge_packages_from_a_list_of_kernels)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "prints 'generally recommended' message" do
|
14
|
+
$stdout.should_receive(:puts).
|
15
|
+
with("It's generally recommended to leave at least three of your latest kernels installed.\n\n")
|
16
|
+
DeKernel.run
|
17
|
+
end
|
18
|
+
|
19
|
+
it "calls Cernel.purge_packages_from_a_list_of_kernels(Cernel.ask_which_to_remove)" do
|
20
|
+
Cernel.should_receive(:ask_which_to_remove)
|
21
|
+
Cernel.should_receive(:purge_packages_from_a_list_of_kernels)
|
22
|
+
DeKernel.run
|
23
|
+
end
|
24
|
+
|
25
|
+
it "prints Message.other_kernels" do
|
26
|
+
$stdout.should_receive(:puts)
|
27
|
+
Message.should_receive(:other_kernels)
|
28
|
+
DeKernel.run
|
29
|
+
end
|
30
|
+
|
31
|
+
it "prints 'disk space freed' message" do
|
32
|
+
$stdout.should_receive(:puts).with("0 megabytes of disk space were freed.")
|
33
|
+
DeKernel.run
|
34
|
+
end
|
35
|
+
|
36
|
+
it "accepts a list of kernels to remove" do
|
37
|
+
$options[:kernels_list] = @remove_kernels.join(" ")
|
38
|
+
Cernel.should_not_receive(:ask_which_to_remove)
|
39
|
+
Cernel.should_receive(:purge_packages_from_a_list_of_kernels).with(@remove_kernels)
|
40
|
+
|
41
|
+
DeKernel.run
|
42
|
+
end
|
43
|
+
|
44
|
+
context "accepts 'all-except (n)' kernels" do
|
45
|
+
it "removes all except latest (n)" do
|
46
|
+
$options[:all_except] = 1
|
47
|
+
$options[:kernels_list] = @remove_kernels.join(" ")
|
48
|
+
Cernel.should_not_receive(:ask_which_to_remove)
|
49
|
+
Cernel.should_not_receive(:purge_packages_from_a_list_of_kernels).with($options[:kernels_list].split(" "))
|
50
|
+
Cernel.should_receive(:find_all_except_latest).with(1)
|
51
|
+
Cernel.should_receive(:purge_packages_from_a_list_of_kernels)
|
52
|
+
|
53
|
+
DeKernel.run
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
require 'dekernel'
|
5
|
+
require 'dekernel/cernel'
|
6
|
+
require 'dekernel/message'
|
7
|
+
|
8
|
+
RSpec.configure do |c|
|
9
|
+
c.before :all do
|
10
|
+
$options = { dry_run: false, assume_yes: false, kernels_list: nil,
|
11
|
+
all_except: nil, no_confirm: false }
|
12
|
+
|
13
|
+
@all_kernels = ["2.3.56-1", "2.4.28-11", "3.2.0-11", "3.2.0-8"]
|
14
|
+
@installed_kernels = @all_kernels.drop(1)
|
15
|
+
@all_except_latest_one = @installed_kernels - ["3.2.0-11"]
|
16
|
+
@kernels_hash = { all: @all_kernels, installed: @installed_kernels }
|
17
|
+
@other_kernels = @all_kernels - @installed_kernels
|
18
|
+
@remove_kernels = @installed_kernels.drop(1)
|
19
|
+
|
20
|
+
@remove_packages = @remove_kernels.collect { |kernel|
|
21
|
+
["linux-headers-#{kernel}",
|
22
|
+
"linux-headers-#{kernel}-generic",
|
23
|
+
"linux-image-#{kernel}-generic"]
|
24
|
+
}.flatten
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dekernel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- david amick
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.11'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.11'
|
30
|
+
description: deKernel is a simple tool that finds installed kernels and automates
|
31
|
+
the removal of any you choose, freeing disk space. With optional flags, it can also
|
32
|
+
be automated for scripting.
|
33
|
+
email: github@davidamick.com
|
34
|
+
executables:
|
35
|
+
- dekernel
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- bin/dekernel
|
40
|
+
- lib/dekernel.rb
|
41
|
+
- lib/dekernel/cernel.rb
|
42
|
+
- lib/dekernel/message.rb
|
43
|
+
- spec/spec_helper.rb
|
44
|
+
- spec/lib/dekernel_spec.rb
|
45
|
+
- spec/lib/dekernel/cernel_spec.rb
|
46
|
+
- spec/lib/dekernel/message_spec.rb
|
47
|
+
homepage: https://github.com/snarlysodboxer/deKernel#dekernel
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.23
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Remove old/unused kernel packages.
|
71
|
+
test_files:
|
72
|
+
- spec/spec_helper.rb
|
73
|
+
- spec/lib/dekernel_spec.rb
|
74
|
+
- spec/lib/dekernel/cernel_spec.rb
|
75
|
+
- spec/lib/dekernel/message_spec.rb
|