zypper-onlinesearch 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|