machinery-tool 1.16.4 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.git_revision +1 -1
  3. data/NEWS +10 -0
  4. data/filters/default_filters.json +21 -20
  5. data/html/assets/machinery-base.js +4 -0
  6. data/html/index.html.haml +1 -1
  7. data/html/partials/changed_managed_files.html.haml +2 -2
  8. data/html/partials/compare/changed_managed_file_list.html.haml +2 -2
  9. data/html/partials/compare/changed_managed_files.html.haml +3 -3
  10. data/html/partials/compare/config_file_list.html.haml +2 -2
  11. data/html/partials/compare/config_files.html.haml +3 -3
  12. data/html/partials/compare/packages.html.haml +21 -4
  13. data/html/partials/compare/repositories.html.haml +10 -7
  14. data/html/partials/compare/repository_list_apt.html.haml +15 -0
  15. data/html/partials/compare/repository_list_yum.html.haml +35 -0
  16. data/html/partials/compare/{repository_list.html.haml → repository_list_zypp.html.haml} +0 -0
  17. data/html/partials/compare/service_list.html.haml +1 -1
  18. data/html/partials/compare/services.html.haml +3 -3
  19. data/html/partials/compare/unmanaged_file_list.html.haml +2 -2
  20. data/html/partials/compare/unmanaged_files.html.haml +1 -1
  21. data/html/partials/config_files.html.haml +39 -41
  22. data/html/partials/repositories.html.haml +1 -23
  23. data/html/partials/repositories_apt.html.haml +15 -0
  24. data/html/partials/repositories_yum.html.haml +30 -0
  25. data/html/partials/repositories_zypp.html.haml +24 -0
  26. data/html/partials/services.html.haml +2 -2
  27. data/html/partials/unmanaged_files.html.haml +2 -2
  28. data/inspect_helpers/dpkg_unmanaged_files.sh +47 -0
  29. data/inspect_helpers/yum_repositories.py +3 -5
  30. data/lib/analyze_config_file_diffs_task.rb +11 -1
  31. data/lib/array.rb +97 -35
  32. data/lib/autoyast.rb +13 -2
  33. data/lib/cli.rb +10 -2
  34. data/lib/config.rb +4 -4
  35. data/lib/dpkg_database.rb +68 -0
  36. data/lib/element_filter.rb +2 -0
  37. data/lib/file_diff.rb +2 -2
  38. data/lib/file_scope.rb +10 -49
  39. data/lib/file_validator.rb +10 -4
  40. data/lib/filter.rb +6 -6
  41. data/lib/filter_option_parser.rb +1 -1
  42. data/lib/kiwi_config.rb +13 -10
  43. data/lib/machinery.rb +2 -0
  44. data/lib/machinery_helper.rb +1 -1
  45. data/lib/managed_files_database.rb +200 -0
  46. data/lib/object.rb +5 -3
  47. data/lib/remote_system.rb +43 -10
  48. data/lib/renderer.rb +3 -4
  49. data/lib/rpm_database.rb +7 -183
  50. data/lib/scope_file_access_archive.rb +3 -3
  51. data/lib/scope_file_access_flat.rb +1 -1
  52. data/lib/server.rb +7 -2
  53. data/lib/system.rb +50 -22
  54. data/lib/system_description.rb +3 -3
  55. data/lib/version.rb +1 -1
  56. data/lib/workload_mapper.rb +2 -2
  57. data/machinery-helper/machinery_helper.go +252 -178
  58. data/machinery-helper/machinery_helper_test.go +121 -121
  59. data/machinery-helper/mountpoints.go +28 -28
  60. data/machinery-helper/tar.go +105 -104
  61. data/machinery-helper/version.go +1 -1
  62. data/man/generated/machinery.1.gz +0 -0
  63. data/man/generated/machinery.1.html +19 -8
  64. data/plugins/changed_managed_files/changed_managed_files_inspector.rb +3 -3
  65. data/plugins/changed_managed_files/changed_managed_files_model.rb +3 -1
  66. data/plugins/changed_managed_files/changed_managed_files_renderer.rb +2 -2
  67. data/plugins/changed_managed_files/schema/system-description-changed-managed-files.schema-v6.json +168 -0
  68. data/plugins/config_files/config_files_inspector.rb +4 -4
  69. data/plugins/config_files/config_files_model.rb +3 -1
  70. data/plugins/config_files/config_files_renderer.rb +2 -2
  71. data/plugins/config_files/schema/system-description-config-files.schema-v6.json +160 -0
  72. data/plugins/environment/schema/system-description-environment.schema-v6.json +17 -0
  73. data/plugins/groups/schema/system-description-groups.schema-v6.json +49 -0
  74. data/plugins/os/schema/system-description-os.schema-v6.json +21 -0
  75. data/plugins/packages/packages_inspector.rb +76 -6
  76. data/plugins/packages/packages_model.rb +31 -12
  77. data/plugins/packages/packages_renderer.rb +5 -2
  78. data/plugins/packages/schema/system-description-packages.schema-v6.json +115 -0
  79. data/plugins/patterns/patterns_inspector.rb +26 -2
  80. data/plugins/patterns/schema/system-description-patterns.schema-v6.json +58 -0
  81. data/plugins/repositories/repositories_inspector.rb +41 -14
  82. data/plugins/repositories/repositories_model.rb +55 -12
  83. data/plugins/repositories/repositories_renderer.rb +23 -7
  84. data/plugins/repositories/schema/system-description-repositories.schema-v6.json +165 -0
  85. data/plugins/services/schema/system-description-services.schema-v6.json +93 -0
  86. data/plugins/services/services_inspector.rb +88 -22
  87. data/plugins/services/services_model.rb +9 -15
  88. data/plugins/services/services_renderer.rb +2 -2
  89. data/plugins/unmanaged_files/schema/system-description-unmanaged-files.schema-v6.json +162 -0
  90. data/plugins/unmanaged_files/unmanaged_files_inspector.rb +80 -30
  91. data/plugins/unmanaged_files/unmanaged_files_model.rb +22 -18
  92. data/plugins/unmanaged_files/unmanaged_files_renderer.rb +3 -3
  93. data/plugins/users/schema/system-description-users.schema-v6.json +86 -0
  94. data/schema/migrations/migrate5to6.rb +101 -0
  95. data/schema/system-description-global.schema-v6.json +43 -0
  96. metadata +24 -4
  97. data/html/assets/landing_page/landing_page.js +0 -10
@@ -24,28 +24,28 @@ class ServicesInspector < Inspector
24
24
  end
25
25
 
26
26
  def inspect(_filter, _options = {})
27
- if @description.environment.system_type == "docker"
28
- result = ServicesScope.new(
29
- init_system: "none",
30
- services: []
31
- )
32
- elsif @system.has_command?("systemctl")
33
- result = ServicesScope.new(
34
- init_system: "systemd",
35
- services: inspect_systemd_services
36
- )
37
- else
38
- result = ServicesScope.new(
39
- init_system: "sysvinit",
40
- services: inspect_sysvinit_services
41
- )
42
- end
43
-
44
- @description.services = result
27
+ services, init_system =
28
+ case
29
+ when @description.environment.system_type == "docker"
30
+ then [[], "none"]
31
+ when @system.has_command?("systemctl")
32
+ then [inspect_systemd_services, "systemd"]
33
+ when @system.has_command?("initctl") && @system.has_command?("chkconfig")
34
+ then [parse_redhat_chkconfig.map { |s| s["legacy_sysv"] = true; s }, "upstart"]
35
+ when @system.has_command?("initctl") && !@system.has_command?("chkconfig")
36
+ then [inspect_ubuntu_services, "upstart"]
37
+ else
38
+ [inspect_sysvinit_services, "sysvinit"]
39
+ end
40
+
41
+ @description.services = ServicesScope.new(
42
+ services,
43
+ init_system: init_system
44
+ )
45
45
  end
46
46
 
47
47
  def summary
48
- "Found #{@description.services.services.length} services."
48
+ "Found #{@description.services.length} services."
49
49
  end
50
50
 
51
51
  private
@@ -68,7 +68,7 @@ class ServicesInspector < Inspector
68
68
  Service.new(name: name, state: state)
69
69
  end
70
70
 
71
- ServiceList.new(services.sort_by(&:name))
71
+ services.sort_by(&:name)
72
72
  end
73
73
 
74
74
  def inspect_sysvinit_services
@@ -84,7 +84,73 @@ class ServicesInspector < Inspector
84
84
  services = parse_suse_chkconfig
85
85
  end
86
86
 
87
- ServiceList.new(services.sort_by(&:name))
87
+ services.sort_by(&:name)
88
+ end
89
+
90
+ def inspect_ubuntu_services
91
+ # Ubuntu is managing its services using upstart but also has some
92
+ # services still not handled by that. Therefor we need to scan upstart
93
+ # and sysV to determine all services and their bootup state
94
+ services = parse_ubuntu_upstart
95
+ parse_ubuntu_sysv.each do |service|
96
+ services << service unless services.find { |s| s.name == service.name }
97
+ end
98
+
99
+ services.sort_by(&:name)
100
+ end
101
+
102
+ def parse_ubuntu_upstart
103
+ initctl_output = @system.run_command("/sbin/initctl", "show-config", "-e", stdout: :capture)
104
+
105
+ servicelist = initctl_output.lines.map(&:chomp).slice_before { |l| !l.start_with?(" ") }
106
+ enabled, disabled = servicelist.partition do |s|
107
+ s.find { |e| e.start_with?(" start on runlevel", " start on startup") }
108
+ end
109
+
110
+ services = enabled.map(&:first).each.map do |name|
111
+ Service.new(name: name, state: "enabled", legacy_sysv: false)
112
+ end
113
+ services + disabled.map(&:first).each.map do |name|
114
+ Service.new(name: name, state: "disabled", legacy_sysv: false)
115
+ end
116
+ end
117
+
118
+ def parse_ubuntu_sysv
119
+ # Get all sysV services
120
+ out, err = @system.run_command(
121
+ "/usr/sbin/service",
122
+ "--status-all",
123
+ stdout: :capture, stderr: :capture)
124
+ services_output = out + err
125
+
126
+ sysv_all = services_output.each_line.map { |line|
127
+ line.chomp.sub(/^.*\]../, "")
128
+ }
129
+
130
+ # Get all enabled sysV services - default in ubuntu1404 is runlevel 2
131
+ # and runlevels 3,4 and 5 are considered to be identical to 2.
132
+ runlevels = ["2", "S"]
133
+ find_output = runlevels.each.map do |runlevel|
134
+ @system.run_command(
135
+ "/usr/bin/find",
136
+ "/etc/rc#{runlevel}.d",
137
+ "-name",
138
+ "S\*",
139
+ stdout: :capture).split
140
+ end
141
+
142
+ sysv_enabled = find_output.flatten.map { |line|
143
+ line.chomp.sub(/^\/etc\/rc.\.d\/.../, "")
144
+ }.uniq
145
+ sysv_disabled = sysv_all - sysv_enabled
146
+
147
+ services = sysv_enabled.map.each do |name|
148
+ Service.new(name: name, state: "enabled", legacy_sysv: true)
149
+ end
150
+
151
+ services + sysv_disabled.map.each do |name|
152
+ Service.new(name: name, state: "disabled", legacy_sysv: true)
153
+ end
88
154
  end
89
155
 
90
156
  def parse_suse_chkconfig
@@ -97,7 +163,7 @@ class ServicesInspector < Inspector
97
163
  :stdout => :capture
98
164
  )
99
165
 
100
- services = output.lines.map do |line|
166
+ output.lines.map do |line|
101
167
  name, state = line.split(/\s+/)
102
168
  Service.new(name: name, state: state)
103
169
  end
@@ -28,21 +28,19 @@ class Service < Machinery::Object
28
28
  end
29
29
  end
30
30
 
31
- class ServiceList < Machinery::Array
32
- has_elements class: Service
33
- end
34
-
35
- class ServicesScope < Machinery::Object
31
+ class ServicesScope < Machinery::Array
36
32
  include Machinery::Scope
37
- has_property :services, class: ServiceList
33
+
34
+ has_attributes :init_system
35
+ has_elements class: Service
38
36
 
39
37
  def compare_with(other)
40
38
  if self.init_system != other.init_system
41
39
  [self, other, nil, nil]
42
40
  else
43
- only_self = self.services - other.services
44
- only_other = other.services - self.services
45
- common = self.services & other.services
41
+ only_self = self - other
42
+ only_other = other - self
43
+ common = self & other
46
44
  changed = Machinery::Scope.extract_changed_elements(only_self, only_other, :name)
47
45
  changed = nil if changed.empty?
48
46
 
@@ -51,17 +49,13 @@ class ServicesScope < Machinery::Object
51
49
  service_list_to_scope(only_other),
52
50
  changed,
53
51
  service_list_to_scope(common)
54
- ]
52
+ ].map { |e| (e && !e.empty?) ? e : nil }
55
53
  end
56
54
  end
57
55
 
58
- def length
59
- services.try(:length) || 0
60
- end
61
-
62
56
  private
63
57
 
64
58
  def service_list_to_scope(services)
65
- self.class.new(init_system: init_system, services: services) if !services.empty?
59
+ self.class.new(services, init_system: init_system) unless services.elements.empty?
66
60
  end
67
61
  end
@@ -19,12 +19,12 @@ class ServicesRenderer < Renderer
19
19
  def content(description)
20
20
  return unless description["services"]
21
21
 
22
- if description["services"].services.empty?
22
+ if description["services"].elements.empty?
23
23
  puts "There are no services."
24
24
  end
25
25
 
26
26
  list do
27
- description["services"].services.each do |p|
27
+ description["services"].each do |p|
28
28
  item "#{p.name}: #{p.state}"
29
29
  end
30
30
  end
@@ -0,0 +1,162 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+
4
+ "type": "object",
5
+ "required": [
6
+ "_elements"
7
+ ],
8
+ "properties": {
9
+ "_attributes": {
10
+ "type": "object",
11
+ "required": [
12
+ "extracted"
13
+ ],
14
+ "properties": {
15
+ "extracted": {
16
+ "type": "boolean"
17
+ }
18
+ }
19
+ },
20
+ "_elements": {
21
+ "oneOf": [
22
+ {
23
+ "type": "array",
24
+ "maxItems": 0
25
+ },
26
+ {
27
+ "type": "array",
28
+ "minItems": 1,
29
+ "items": {
30
+ "anyOf": [
31
+ {
32
+ "$ref": "#/definitions/file_extracted"
33
+ },
34
+ {
35
+ "$ref": "#/definitions/file_remote_dir"
36
+ }
37
+ ]
38
+ }
39
+ },
40
+ {
41
+ "type": "array",
42
+ "minItems": 1,
43
+ "items": {
44
+ "anyOf": [
45
+ {
46
+ "$ref": "#/definitions/file_not_extracted"
47
+ },
48
+ {
49
+ "$ref": "#/definitions/file_remote_dir"
50
+ }
51
+ ]
52
+ }
53
+ }
54
+ ]
55
+ }
56
+ },
57
+ "definitions": {
58
+ "file_common": {
59
+ "type": "object",
60
+ "required": ["name"],
61
+ "properties": {
62
+ "name": {
63
+ "type": "string"
64
+ }
65
+ }
66
+ },
67
+ "file_not_extracted": {
68
+ "allOf": [
69
+ { "$ref": "#/definitions/file_common" },
70
+ {
71
+ "required": ["type"],
72
+ "properties": {
73
+ "type": {
74
+ "enum": ["file", "dir", "link", "remote_dir"]
75
+ }
76
+ },
77
+ "not": { "$ref": "#/definitions/file_extracted" }
78
+ }
79
+ ]
80
+ },
81
+ "file_extracted": {
82
+ "allOf": [
83
+ { "$ref": "#/definitions/file_common" },
84
+ {
85
+ "required": ["user", "group"],
86
+ "properties": {
87
+ "user": {
88
+ "type": "string",
89
+ "minLength": 1
90
+ },
91
+ "group": {
92
+ "type": "string",
93
+ "minLength": 1
94
+ }
95
+ },
96
+ "oneOf": [
97
+ { "$ref": "#/definitions/file_extracted_file" },
98
+ { "$ref": "#/definitions/file_extracted_dir" },
99
+ { "$ref": "#/definitions/file_extracted_link" }
100
+ ]
101
+ }
102
+ ]
103
+ },
104
+ "file_extracted_file": {
105
+ "required": ["type", "size", "mode"],
106
+ "properties": {
107
+ "type": {
108
+ "enum": ["file"]
109
+ },
110
+ "size": {
111
+ "type": "integer",
112
+ "minimum": 0
113
+ },
114
+ "mode": {
115
+ "type": "string",
116
+ "pattern": "^[0-7]{3,4}$"
117
+ }
118
+ }
119
+ },
120
+ "file_extracted_dir": {
121
+ "required": ["type", "size", "mode", "files"],
122
+ "properties": {
123
+ "type": {
124
+ "enum": ["dir"]
125
+ },
126
+ "size": {
127
+ "type": "integer",
128
+ "minimum": 0
129
+ },
130
+ "mode": {
131
+ "type": "string",
132
+ "pattern": "^[0-4]?[0-7]{3}$"
133
+ },
134
+ "files": {
135
+ "type": "integer",
136
+ "minimum": 1
137
+ }
138
+ }
139
+ },
140
+ "file_extracted_link": {
141
+ "required": ["type"],
142
+ "properties": {
143
+ "type": {
144
+ "enum": ["link"]
145
+ }
146
+ }
147
+ },
148
+ "file_remote_dir": {
149
+ "allOf": [
150
+ { "$ref": "#/definitions/file_common" },
151
+ {
152
+ "required": ["type"],
153
+ "properties": {
154
+ "type": {
155
+ "enum": ["remote_dir"]
156
+ }
157
+ }
158
+ }
159
+ ]
160
+ }
161
+ }
162
+ }
@@ -20,7 +20,7 @@ class UnmanagedFilesInspector < Inspector
20
20
 
21
21
  # checks if all required binaries are present
22
22
  def check_requirements(check_tar)
23
- @system.check_requirement("rpm", "--version")
23
+ @system.check_requirement(["rpm", "dpkg"], "--version")
24
24
  @system.check_requirement("sed", "--version")
25
25
  @system.check_requirement("cat", "--version")
26
26
  @system.check_requirement("find", "--version")
@@ -34,6 +34,7 @@ class UnmanagedFilesInspector < Inspector
34
34
  ["sed", "s/^\\(.\\)[^/]* /\\1 /"],
35
35
  :stdout => :capture
36
36
  )
37
+
37
38
  files = {}
38
39
  dirh = {}
39
40
  links = {}
@@ -52,13 +53,27 @@ class UnmanagedFilesInspector < Inspector
52
53
  files[pair.first] = pair[1]
53
54
  end
54
55
  end
56
+
57
+ process_managed_files_and_dirs(files, dirh)
58
+ end
59
+
60
+ def extract_dpkg_database
61
+ out = @system.run_script_with_progress("dpkg_unmanaged_files.sh")
62
+ parsed_data = parse_dpkg_package_files_output(out)
63
+ files = parsed_data[:files]
64
+ dirh = parsed_data[:directories]
65
+
66
+ process_managed_files_and_dirs(files, dirh)
67
+ end
68
+
69
+ def process_managed_files_and_dirs(files, dirs)
55
70
  # make sure that all parent directories of managed rpm directories are considered
56
71
  # managed
57
- dirh.dup.keys.each do |d|
72
+ dirs.dup.keys.each do |d|
58
73
  dir = d.rpartition("/").first
59
74
 
60
- while !dirh.has_key?(dir) && dir.size > 1
61
- dirh[dir] = false
75
+ while !dirs.key?(dir) && dir.size > 1
76
+ dirs[dir] = false
62
77
  dir = dir[0..dir.rindex("/") - 1]
63
78
  end
64
79
  end
@@ -68,18 +83,36 @@ class UnmanagedFilesInspector < Inspector
68
83
 
69
84
  # make sure that dirs leading to a managed file are treated as if they were
70
85
  # in rpm database, otherwise we cannot exclude whole unmanaged trees
71
- while( !dirh.has_key?(dir) && dir.size > 1 )
72
- dirh[dir] = false
86
+ while !dirs.key?(dir) && dir.size > 1
87
+ dirs[dir] = false
73
88
  dir=dir[0..dir.rindex("/") - 1]
74
89
  end
75
90
 
76
91
  # put links to a managed directory also into directory hash
77
- if !e.empty? && dirh.has_key?(e)
78
- dirh[f] = false
92
+ if !e.empty? && dirs.key?(e)
93
+ dirs[f] = false
79
94
  end
80
95
  end
81
- Machinery.logger.debug "extract_rpm_database files:#{files.size} dirs:#{dirh.size}"
82
- [files, dirh]
96
+
97
+ [files, dirs]
98
+ end
99
+
100
+ def parse_dpkg_package_files_output(data)
101
+ result = { files: {}, directories: {} }
102
+
103
+ data.each_line do |line|
104
+ type, value = line.chomp.split(" ", 2)
105
+
106
+ if type == "-" # file
107
+ result[:files][value] = ""
108
+ elsif type == "d" && value != "/." # directory
109
+ result[:directories][value] = true
110
+ elsif type == "l" # link
111
+ pair = value.split(" -> ", 2)
112
+ result[:files][pair[0]] = pair[1]
113
+ end
114
+ end
115
+ result
83
116
  end
84
117
 
85
118
  def check_consistency(files, dirh)
@@ -219,6 +252,8 @@ class UnmanagedFilesInspector < Inspector
219
252
  do_extract = options && options[:extract_unmanaged_files]
220
253
  check_requirements(do_extract)
221
254
 
255
+ determine_package_manager
256
+
222
257
  scope = UnmanagedFilesScope.new
223
258
 
224
259
  file_store_tmp = @description.scope_file_store("unmanaged_files.tmp")
@@ -226,8 +261,8 @@ class UnmanagedFilesInspector < Inspector
226
261
 
227
262
  scope.scope_file_store = file_store_tmp
228
263
 
229
- file_filter = filter.element_filter_for("/unmanaged_files/files/name").dup if filter
230
- file_filter ||= ElementFilter.new("/unmanaged_files/files/name")
264
+ file_filter = filter.element_filter_for("/unmanaged_files/name").dup if filter
265
+ file_filter ||= ElementFilter.new("/unmanaged_files/name")
231
266
  file_filter.add_matchers("=", @description.store.base_path)
232
267
 
233
268
  # Add a recursive pendant to each ignored element
@@ -244,6 +279,14 @@ class UnmanagedFilesInspector < Inspector
244
279
  end
245
280
  end
246
281
 
282
+ def determine_package_manager
283
+ if @system.has_command?("rpm")
284
+ @package_manager = "rpm"
285
+ elsif @system.has_command?("dpkg")
286
+ @package_manager = "dpkg"
287
+ end
288
+ end
289
+
247
290
  def helper_usable?(helper)
248
291
  if !helper.can_help?
249
292
  Machinery::Ui.puts(
@@ -254,7 +297,7 @@ class UnmanagedFilesInspector < Inspector
254
297
  Machinery::Ui.puts(
255
298
  "Note: Using traditional inspection because only 'root' is supported as remote user."
256
299
  )
257
- else
300
+ elsif ["rpm", "dpkg"].include?(@package_manager)
258
301
  return true
259
302
  end
260
303
 
@@ -272,8 +315,7 @@ class UnmanagedFilesInspector < Inspector
272
315
  end
273
316
 
274
317
  helper.run_helper(scope)
275
-
276
- scope.files.delete_if { |f| filter.matches?(f.name) }
318
+ scope.delete_if { |f| filter.matches?(f.name) }
277
319
 
278
320
  if do_extract
279
321
  mount_points = MountPoints.new(@system)
@@ -282,16 +324,16 @@ class UnmanagedFilesInspector < Inspector
282
324
  file_store_tmp.remove
283
325
  file_store_tmp.create
284
326
 
285
- files = scope.files.select { |f| f.file? || f.link? }.map(&:name)
327
+ files = scope.select { |f| f.file? || f.link? }.map(&:name)
286
328
  scope.retrieve_files_from_system_as_archive(@system, files, [])
287
329
  show_extraction_progress(files.count)
288
330
 
289
331
  scope.retrieve_trees_from_system_as_archive(@system,
290
- scope.files.select(&:directory?).map(&:name), excluded_trees) do |count|
332
+ scope.select(&:directory?).map(&:name), excluded_trees) do |count|
291
333
  show_extraction_progress(files.count + count)
292
334
  end
293
335
 
294
- scope.files = extract_tar_metadata(scope.files, file_store_tmp.path)
336
+ scope = extract_tar_metadata(scope, file_store_tmp.path)
295
337
  file_store_final.remove
296
338
  file_store_tmp.rename(file_store_final.store_name)
297
339
  scope.scope_file_store = file_store_final
@@ -310,7 +352,11 @@ class UnmanagedFilesInspector < Inspector
310
352
  def run_inspection(file_filter, options, do_extract, file_store_tmp, file_store_final, scope)
311
353
  mount_points = MountPoints.new(@system)
312
354
 
313
- rpm_files, rpm_dirs = extract_rpm_database
355
+ if @package_manager == "rpm"
356
+ inspected_files, inspected_dirs = extract_rpm_database
357
+ elsif @package_manager == "dpkg"
358
+ inspected_files, inspected_dirs = extract_dpkg_database
359
+ end
314
360
 
315
361
  # Btrfs subvolumes and local mounts need to be inspected separately because
316
362
  # they are not part of the `get_find_data` return data
@@ -359,7 +405,8 @@ class UnmanagedFilesInspector < Inspector
359
405
  if !local_filesystems.empty?
360
406
  # force all mount points to be non-leave directories (find is called with -xdev)
361
407
  local_filesystems.each do |mp|
362
- dirs[mp] = true if dirs.has_key?(mp)
408
+ path = mp.sub(/^\//, "")
409
+ dirs[path] = true if dirs.key?(path)
363
410
  end
364
411
  local_filesystems.reject! { |mp| dirs.has_key?(mp) }
365
412
  end
@@ -372,7 +419,7 @@ class UnmanagedFilesInspector < Inspector
372
419
  file_filter.matches?("/" + dir)
373
420
  end
374
421
  end
375
- managed, unmanaged = dirs.keys.partition{ |d| rpm_dirs.has_key?(find_dir + d) }
422
+ managed, unmanaged = dirs.keys.partition { |d| inspected_dirs.key?(find_dir + d) }
376
423
 
377
424
  # unmanaged dirs lead to removal of files and dirs below that dir
378
425
  while !unmanaged.empty?
@@ -408,7 +455,7 @@ class UnmanagedFilesInspector < Inspector
408
455
  dirs_todo.push(*managed)
409
456
 
410
457
  # unmanaged files are simply stored
411
- managed, unmanaged = files.keys.partition{ |d| rpm_files.has_key?(find_dir + d) }
458
+ managed, unmanaged = files.keys.partition { |d| inspected_files.key?(find_dir + d) }
412
459
  links = unmanaged.reject { |d| files[d].empty? }
413
460
  unmanaged.map!{ |d| find_dir + d }
414
461
  unmanaged_files.push(*unmanaged)
@@ -426,8 +473,7 @@ class UnmanagedFilesInspector < Inspector
426
473
  excluded_files, remote_dirs, do_extract, file_store_tmp, file_store_final, scope)
427
474
 
428
475
  scope.extracted = !!do_extract
429
- scope.files = UnmanagedFileList.new(processed_files.sort_by(&:name))
430
-
476
+ scope += processed_files.sort_by(&:name)
431
477
  @description["unmanaged_files"] = scope
432
478
  end
433
479
 
@@ -477,7 +523,7 @@ class UnmanagedFilesInspector < Inspector
477
523
 
478
524
  def summary
479
525
  "#{@description.unmanaged_files.extracted ? "Extracted" : "Found"} " +
480
- "#{@description.unmanaged_files.files.count} unmanaged files and trees."
526
+ "#{@description.unmanaged_files.count} unmanaged files and trees."
481
527
  end
482
528
 
483
529
  private
@@ -490,10 +536,14 @@ class UnmanagedFilesInspector < Inspector
490
536
  end
491
537
 
492
538
  def btrfs_subvolumes
493
- @system.run_command(
494
- ["btrfs", "subvolume", "list", "/"],
495
- ["awk", "{print $NF}"],
496
- stdout: :capture
497
- ).split
539
+ if @system.has_command?("/sbin/btrfs")
540
+ @system.run_command(
541
+ ["/sbin/btrfs", "subvolume", "list", "/"],
542
+ ["awk", "{print $NF}"],
543
+ stdout: :capture
544
+ ).split
545
+ else
546
+ []
547
+ end
498
548
  end
499
549
  end