zypper-onlinesearch 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +81 -0
- data/Gemfile +12 -2
- data/Gemfile.lock +36 -5
- data/LICENSE +674 -0
- data/README.md +8 -104
- data/Rakefile +7 -1
- data/lib/zypper/onlinesearch/cache.rb +20 -23
- data/lib/zypper/onlinesearch/cli.rb +63 -61
- data/lib/zypper/onlinesearch/data.rb +116 -106
- data/lib/zypper/onlinesearch/release.rb +13 -12
- data/lib/zypper/onlinesearch/request.rb +62 -54
- data/lib/zypper/onlinesearch/utils.rb +64 -26
- data/lib/zypper/onlinesearch/version.rb +3 -1
- data/lib/zypper/onlinesearch/view.rb +188 -155
- data/lib/zypper/onlinesearch.rb +69 -90
- data/zypper-onlinesearch.gemspec +20 -23
- metadata +12 -56
- data/.gitignore +0 -11
- data/.travis.yml +0 -5
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -1,50 +1,54 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
2
4
|
|
3
5
|
module Zypper
|
4
6
|
module Onlinesearch
|
5
|
-
|
7
|
+
#
|
8
|
+
# Base class for page scraping.
|
9
|
+
#
|
6
10
|
class PageData
|
7
|
-
|
8
11
|
FORMATS = {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
}
|
12
|
+
aarch64: "ARM v8.x 64-bit",
|
13
|
+
aarch64_ilp32: "ARM v8.x 64-bit ilp32 mode",
|
14
|
+
all: "All",
|
15
|
+
armv6l: "ARM v6",
|
16
|
+
armv7l: "ARM v7",
|
17
|
+
extra: "Extra",
|
18
|
+
i586: "Intel 32-bit",
|
19
|
+
i686: "Intel Pentium 32-bit",
|
20
|
+
lang: "Language",
|
21
|
+
lsrc: "Language source",
|
22
|
+
noarch: "No architecture",
|
23
|
+
ppc64le: "PowerPC 64-bit little-endian",
|
24
|
+
ppc64: "PowerPC 64-bit",
|
25
|
+
ppc: "PowerPC",
|
26
|
+
repo: "Repository",
|
27
|
+
riscv64: "Risc v64",
|
28
|
+
s390x: "IBM System/390",
|
29
|
+
src: "Source",
|
30
|
+
x86_64: "Intel/AMD 64-bit",
|
31
|
+
ymp: "1 Click Install"
|
32
|
+
}.freeze
|
30
33
|
|
31
34
|
def initialize(page)
|
32
35
|
@page = Nokogiri::HTML(page)
|
33
36
|
end
|
34
37
|
|
35
38
|
def expand_link(link)
|
36
|
-
link = [self.class::URL, link].join(
|
37
|
-
URI(link).to_s.gsub(
|
39
|
+
link = [self.class::URL, link].join("/") unless link =~ %r{://}
|
40
|
+
URI(link).to_s.gsub(%r{([^:])//}, '\1/')
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
41
|
-
|
42
44
|
module Data
|
43
|
-
|
44
45
|
module Search
|
46
|
+
#
|
47
|
+
# Scraping class for openSUSE search.
|
48
|
+
#
|
45
49
|
class Opensuse < PageData
|
50
|
+
URL = "https://software.opensuse.org"
|
46
51
|
|
47
|
-
URL = 'https://software.opensuse.org'
|
48
52
|
XPATH_CARDS = '//div[@id="search-result-list"]//div[@class="card-body"]'
|
49
53
|
XPATH_NAME = './/h4[@class="card-title"]'
|
50
54
|
XPATH_DESC = './/p[@class="card-text"]'
|
@@ -59,17 +63,14 @@ module Zypper
|
|
59
63
|
cards.each do |c|
|
60
64
|
url = expand_link(c.xpath(XPATH_URL).text)
|
61
65
|
name = c.xpath(XPATH_NAME).text
|
62
|
-
name =
|
63
|
-
res << { name: name, description: c.xpath(XPATH_DESC).text.strip.gsub(/\n|\ +/,
|
66
|
+
name = File.basename(url) == name ? name : "#{File.basename(url)} (#{name})"
|
67
|
+
res << { name: name, description: c.xpath(XPATH_DESC).text.strip.gsub(/\n|\ +/, " "), url: url }
|
64
68
|
end
|
65
69
|
|
66
|
-
if res.empty?
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
unless name.to_s.empty?
|
71
|
-
res << { name: name, description: @page.xpath(Page::Opensuse::XPATH_SHORTDESC).text.strip }
|
72
|
-
end
|
70
|
+
if res.empty? && @page.xpath(XPATH_ERROR).text.empty?
|
71
|
+
name = @page.xpath(Page::Opensuse::XPATH_NAME).text
|
72
|
+
unless name.to_s.empty?
|
73
|
+
res << { name: name, description: @page.xpath(Page::Opensuse::XPATH_SHORTDESC).text.strip }
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
@@ -77,9 +78,11 @@ module Zypper
|
|
77
78
|
end
|
78
79
|
end
|
79
80
|
|
81
|
+
#
|
82
|
+
# Scraping class for Packman search.
|
83
|
+
#
|
80
84
|
class Packman < PageData
|
81
|
-
|
82
|
-
URL = 'http://packman.links2linux.org'
|
85
|
+
URL = "http://packman.links2linux.org"
|
83
86
|
|
84
87
|
XPATH_PACKAGE = '//table[@id="packagelist"]//tr'
|
85
88
|
XPATH_NAME = './/td[@class="package-name"]/a'
|
@@ -88,10 +91,15 @@ module Zypper
|
|
88
91
|
|
89
92
|
def data
|
90
93
|
res = []
|
91
|
-
|
92
94
|
@page.xpath(XPATH_PACKAGE).each do |pack|
|
93
95
|
name = pack.xpath(XPATH_NAME).text
|
94
|
-
|
96
|
+
next if name.empty?
|
97
|
+
|
98
|
+
res << {
|
99
|
+
name: name,
|
100
|
+
description: pack.xpath(XPATH_DESC).text.strip.gsub(/\n|\ +/, " "),
|
101
|
+
url: expand_link(pack.xpath(XPATH_URL).text)
|
102
|
+
}
|
95
103
|
end
|
96
104
|
|
97
105
|
if res.empty?
|
@@ -104,38 +112,45 @@ module Zypper
|
|
104
112
|
|
105
113
|
res
|
106
114
|
end
|
107
|
-
|
108
115
|
end
|
109
116
|
end
|
110
117
|
|
111
|
-
|
112
118
|
module Page
|
113
|
-
|
119
|
+
#
|
120
|
+
# Scraping class for openSUSE page.
|
121
|
+
#
|
114
122
|
class Opensuse < PageData
|
123
|
+
URL = "https://software.opensuse.org"
|
115
124
|
|
116
|
-
|
117
|
-
|
118
|
-
XPATH_SHORTDESC = '//h1/following::p/strong'
|
125
|
+
XPATH_NAME = "//h1"
|
126
|
+
XPATH_SHORTDESC = "//h1/following::p/strong"
|
119
127
|
XPATH_DESC = '//*[@id="pkg-desc"]'
|
120
128
|
|
121
129
|
XPATH_SUPPORTED = '//div[@id="other-distributions-listing"]/h4'
|
122
130
|
|
123
|
-
XPATH_SUPPORTED_DISTRO =
|
131
|
+
XPATH_SUPPORTED_DISTRO = "./h4"
|
124
132
|
XPATH_SUPPORTED_LABEL = './/following-sibling::div[@class="card mb-2"][1]//a'
|
125
|
-
XPATH_SUPPORTED_LINK =
|
126
|
-
XPATH_SUPPORTED_VERSION =
|
133
|
+
XPATH_SUPPORTED_LINK = ".//@href"
|
134
|
+
XPATH_SUPPORTED_VERSION = '../..//div[@class="col-md-2"]'
|
127
135
|
|
128
136
|
XPATH_COMMUNITY = './/following-sibling::div[contains(@id,"community-packages")][1]//div/div/a'
|
129
|
-
XPATH_COMMUNITY_LINK =
|
130
|
-
XPATH_COMMUNITY_VERSION =
|
137
|
+
XPATH_COMMUNITY_LINK = ".//@href"
|
138
|
+
XPATH_COMMUNITY_VERSION = '../..//div[@class="col-md-2"]'
|
131
139
|
|
132
140
|
XPATH_EXPERIMENTAL = './/following-sibling::div[contains(@id,"experimental-packages")][1]//div/div/a'
|
133
|
-
XPATH_EXPERIMENTAL_LINK =
|
141
|
+
XPATH_EXPERIMENTAL_LINK = ".//@href"
|
134
142
|
XPATH_EXPERIMENTAL_VERSION = '../..//div[@class="col-md-2"]'
|
135
143
|
|
144
|
+
XPATH_UNSUPPORTED = '//div[@id="unsupported-distributions"]/h4'
|
145
|
+
|
146
|
+
XPATH_UNSUPPORTED_DISTRO = "./h4"
|
147
|
+
XPATH_UNSUPPORTED_LABEL =
|
148
|
+
'.//following-sibling::div[@class="card mb-2" and count(preceding-sibling::h4)=_n_]//a'
|
149
|
+
XPATH_UNSUPPORTED_LINK = ".//@href"
|
150
|
+
XPATH_UNSUPPORTED_VERSION = '../..//div[@class="col-md-2"]'
|
151
|
+
|
136
152
|
def data
|
137
153
|
res = {}
|
138
|
-
|
139
154
|
res[:name] = @page.xpath(XPATH_NAME).text
|
140
155
|
res[:short_description] = @page.xpath(XPATH_SHORTDESC).text.strip
|
141
156
|
res[:description] = @page.xpath(XPATH_DESC).text.chomp
|
@@ -147,17 +162,23 @@ module Zypper
|
|
147
162
|
extract(ver, res, :experimental, XPATH_EXPERIMENTAL, XPATH_EXPERIMENTAL_VERSION, XPATH_EXPERIMENTAL_LINK)
|
148
163
|
end
|
149
164
|
|
165
|
+
@page.xpath(XPATH_UNSUPPORTED).each_with_index do |ver, i|
|
166
|
+
extract(ver, res, :unsupported,
|
167
|
+
XPATH_UNSUPPORTED_LABEL.gsub(/_n_/, i.next.to_s),
|
168
|
+
XPATH_UNSUPPORTED_VERSION, XPATH_UNSUPPORTED_LINK)
|
169
|
+
end
|
170
|
+
|
150
171
|
res
|
151
172
|
end
|
152
173
|
|
153
|
-
|
154
174
|
private
|
155
175
|
|
156
176
|
def extract(ver, res, type, xpath_group, xpath_version, xpath_link)
|
157
|
-
repo =
|
177
|
+
repo = ""
|
178
|
+
format = ""
|
179
|
+
version = nil
|
158
180
|
|
159
181
|
ver.xpath(xpath_group).each do |pack|
|
160
|
-
|
161
182
|
version = pack.xpath(xpath_version).text.strip
|
162
183
|
|
163
184
|
if version.empty?
|
@@ -177,80 +198,76 @@ module Zypper
|
|
177
198
|
end
|
178
199
|
end
|
179
200
|
|
180
|
-
#puts repo, link, format
|
181
201
|
link = expand_link(pack.xpath(xpath_link).text)
|
182
202
|
|
183
203
|
if repo =~ /Expert Download/
|
184
|
-
res[:versions] << { distro: ver.text, link: link, type: type,
|
204
|
+
res[:versions] << { distro: ver.text.gsub(/:/, " "), link: link, type: type,
|
205
|
+
repo: @old_repo, format: :extra, version: version }
|
185
206
|
next
|
186
207
|
end
|
187
208
|
|
188
|
-
next if format.to_s.empty? ||
|
209
|
+
next if format.to_s.empty? || link.include?("/package/show/")
|
189
210
|
|
190
|
-
res[:versions] << { distro: ver.text, link: link, type: type, repo: repo,
|
211
|
+
res[:versions] << { distro: ver.text, link: link, type: type, repo: repo,
|
212
|
+
format: format, version: version }
|
191
213
|
end
|
192
|
-
|
193
214
|
end
|
194
215
|
|
195
216
|
def format?(str)
|
196
|
-
PageData::FORMATS.
|
217
|
+
PageData::FORMATS.value? str
|
197
218
|
end
|
198
|
-
|
199
219
|
end
|
200
220
|
|
201
|
-
|
221
|
+
#
|
222
|
+
# Scraping class for Packman page.
|
223
|
+
#
|
202
224
|
class Packman < PageData
|
203
|
-
|
204
|
-
URL = 'http://packman.links2linux.org'
|
225
|
+
URL = "http://packman.links2linux.org"
|
205
226
|
|
206
227
|
XPATH_NAME = '//td[@id="package-details-header-name"]'
|
207
228
|
XPATH_DESC = '//div[@id="package-description"]'
|
208
229
|
|
209
230
|
XPATH_PACKAGES = '//td[@id="package-details-left"]//tbody/tr'
|
210
|
-
XPATH_VERSION =
|
211
|
-
XPATH_DISTRO =
|
212
|
-
XPATH_FORMAT =
|
213
|
-
XPATH_LINK =
|
231
|
+
XPATH_VERSION = ".//td[1]"
|
232
|
+
XPATH_DISTRO = ".//td[2]"
|
233
|
+
XPATH_FORMAT = ".//td[3]"
|
234
|
+
XPATH_LINK = ".//a/@href"
|
214
235
|
|
215
236
|
def data
|
216
237
|
res = {}
|
217
|
-
|
218
238
|
res[:name] = @page.xpath(XPATH_NAME).text
|
219
|
-
res[:short_description] =
|
239
|
+
res[:short_description] = ""
|
220
240
|
res[:description] = @page.xpath(XPATH_DESC).text
|
221
241
|
res[:versions] = []
|
222
242
|
|
223
|
-
|
224
243
|
@page.xpath(XPATH_PACKAGES).each do |pack|
|
225
|
-
|
226
|
-
|
227
|
-
distro = pack.xpath(XPATH_DISTRO).text.gsub(/_/, ' ')
|
244
|
+
version = pack.xpath(XPATH_VERSION).text.split("-")[0].to_s
|
245
|
+
distro = pack.xpath(XPATH_DISTRO).text.gsub(/_/, " ")
|
228
246
|
format = pack.xpath(XPATH_FORMAT).text.strip.to_sym
|
229
247
|
link = pack.xpath(XPATH_LINK).text
|
230
248
|
|
231
249
|
res[:versions] << { format: format, version: version, distro: distro,
|
232
250
|
type: :supported, link: "http://packman.links2linux.org#{link}",
|
233
|
-
repo:
|
251
|
+
repo: "Packman" }
|
234
252
|
end
|
235
253
|
|
236
254
|
res
|
237
255
|
end
|
238
256
|
end
|
239
|
-
|
240
257
|
end
|
241
258
|
|
242
|
-
|
243
259
|
module Links
|
244
|
-
|
260
|
+
#
|
261
|
+
# Scraping class for openSUSE links.
|
262
|
+
#
|
245
263
|
class Opensuse < PageData
|
246
|
-
|
247
264
|
XPATH_REPO = '//*[@id="manualopenSUSE"]/h5'
|
248
|
-
XPATH_REPO_DISTRO =
|
249
|
-
XPATH_REPO_LINK =
|
265
|
+
XPATH_REPO_DISTRO = "./strong[1]"
|
266
|
+
XPATH_REPO_LINK = "following-sibling::pre[1]"
|
250
267
|
|
251
268
|
XPATH_PACKAGE_GROUP = '//*[@id="directopenSUSE"]/div/div'
|
252
|
-
XPATH_PACKAGE_DISTRO =
|
253
|
-
XPATH_PACKAGE_LINK =
|
269
|
+
XPATH_PACKAGE_DISTRO = "./p/strong"
|
270
|
+
XPATH_PACKAGE_LINK = ".//@href"
|
254
271
|
|
255
272
|
def data
|
256
273
|
res = { versions: [] }
|
@@ -261,52 +278,48 @@ module Zypper
|
|
261
278
|
res
|
262
279
|
end
|
263
280
|
|
264
|
-
|
265
281
|
private
|
266
282
|
|
267
283
|
def extract(res, format_idx, xpath_group, xpath_distro, xpath_link)
|
268
284
|
@page.xpath(xpath_group).each do |section|
|
269
|
-
distro =
|
285
|
+
distro = ""
|
270
286
|
section.xpath(xpath_distro).each do |subsection|
|
271
287
|
distro = subsection.text
|
272
288
|
distro = "openSUSE Leap #{distro}" if distro =~ /^\d\d.\d$/
|
273
289
|
end
|
274
290
|
|
275
|
-
#p distro
|
276
291
|
section.xpath(xpath_link).each do |subsection|
|
277
292
|
link = subsection.text
|
278
|
-
link = link.gsub("\n",
|
293
|
+
link = link.gsub("\n", " ").scan(%r{(https://[^ \n]+)}).pop.pop
|
279
294
|
res[:versions] << {
|
280
295
|
distro: distro,
|
281
|
-
format: File.basename(link).split(
|
282
|
-
link: link
|
296
|
+
format: File.basename(link).split(".")[format_idx].to_sym,
|
297
|
+
link: link
|
283
298
|
}
|
284
|
-
#p link
|
285
299
|
end
|
286
300
|
end
|
287
|
-
|
288
301
|
end
|
289
302
|
end
|
290
303
|
|
304
|
+
#
|
305
|
+
# Scraping class for Packman links.
|
306
|
+
#
|
291
307
|
class Packman < PageData
|
308
|
+
URL = "http://packman.links2linux.org"
|
292
309
|
|
293
310
|
XPATH_LINK_DISTRO = '//*[@id="selected-release"]/td[2]'
|
294
311
|
XPATH_LINK_BIN = '//*[@id="package-details-binfiles"]//a/@href'
|
295
312
|
XPATH_LINK_SRC = '//*[@id="package-details-srcfile-heading"]//a/@href'
|
296
313
|
XPATH_LINK_YMP = '//*[@class="ymp"]//a/@href'
|
297
314
|
|
298
|
-
URL = 'http://packman.links2linux.org'
|
299
|
-
|
300
315
|
def data
|
301
316
|
res = { versions: [] }
|
302
|
-
|
303
|
-
distro = @page.xpath(XPATH_LINK_DISTRO).text.gsub(/\_/, ' ')
|
304
|
-
|
317
|
+
distro = @page.xpath(XPATH_LINK_DISTRO).text.gsub(/_/, " ")
|
305
318
|
@page.xpath(XPATH_LINK_BIN).each do |pack|
|
306
319
|
link = pack.text
|
307
320
|
res[:versions] << {
|
308
321
|
distro: distro,
|
309
|
-
format: File.basename(link).split(
|
322
|
+
format: File.basename(link).split(".")[-2].to_sym,
|
310
323
|
link: URL + link
|
311
324
|
}
|
312
325
|
end
|
@@ -317,7 +330,7 @@ module Zypper
|
|
317
330
|
link = @page.xpath(XPATH_LINK_SRC).text
|
318
331
|
res[:versions] << {
|
319
332
|
distro: distro,
|
320
|
-
format: is_lang ? :lsrc : File.basename(link).split(
|
333
|
+
format: is_lang ? :lsrc : File.basename(link).split(".")[-2].to_sym,
|
321
334
|
link: URL + link
|
322
335
|
}
|
323
336
|
|
@@ -333,10 +346,7 @@ module Zypper
|
|
333
346
|
res
|
334
347
|
end
|
335
348
|
end
|
336
|
-
|
337
349
|
end
|
338
|
-
|
339
|
-
end # Data module
|
340
|
-
|
350
|
+
end
|
341
351
|
end
|
342
352
|
end
|
@@ -1,30 +1,32 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "iniparse"
|
2
4
|
|
3
5
|
module Zypper
|
4
6
|
module Onlinesearch
|
5
|
-
|
7
|
+
#
|
8
|
+
# Current release classification.
|
9
|
+
#
|
6
10
|
class Release
|
7
|
-
|
8
|
-
|
9
|
-
def initialize()
|
10
|
-
@filename = File.exist?('/etc/SuSE-release') ? '/etc/SuSE-release' : '/etc/os-release'
|
11
|
+
def initialize
|
12
|
+
@filename = File.exist?("/etc/SuSE-release") ? "/etc/SuSE-release" : "/etc/os-release"
|
11
13
|
@ini = IniParse.parse(File.read(@filename))
|
12
14
|
end
|
13
15
|
|
14
16
|
def name
|
15
|
-
ini[
|
17
|
+
ini["NAME"].delete('"')
|
16
18
|
end
|
17
19
|
|
18
20
|
def version
|
19
|
-
ini[
|
21
|
+
ini["VERSION"].delete('"')
|
20
22
|
end
|
21
23
|
|
22
24
|
def id
|
23
|
-
ini[
|
25
|
+
ini["ID"].delete('"')
|
24
26
|
end
|
25
27
|
|
26
28
|
def pretty_name
|
27
|
-
ini[
|
29
|
+
ini["PRETTY_NAME"].delete('"')
|
28
30
|
end
|
29
31
|
|
30
32
|
def arch
|
@@ -34,9 +36,8 @@ module Zypper
|
|
34
36
|
private
|
35
37
|
|
36
38
|
def ini
|
37
|
-
@ini[
|
39
|
+
@ini["__anonymous__"]
|
38
40
|
end
|
39
41
|
end
|
40
|
-
|
41
42
|
end
|
42
43
|
end
|