zypper 0.2.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.
- data/CHANGELOG +16 -0
- data/LICENSE +22 -0
- data/README.markdown +421 -0
- data/VERSION +1 -0
- data/lib/zypper.rb +55 -0
- data/lib/zypper/config.rb +91 -0
- data/lib/zypper/package.rb +115 -0
- data/lib/zypper/patch.rb +113 -0
- data/lib/zypper/repository.rb +35 -0
- data/lib/zypper/service.rb +19 -0
- data/lib/zypper/utils.rb +197 -0
- data/lib/zypper/version.rb +4 -0
- metadata +135 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
0.0.9 (2012-06-26)
|
2
|
+
------------------
|
3
|
+
* Split into smaller one-task libraries
|
4
|
+
* Added plural aliases for for accessing subclasses (patch -> patches,
|
5
|
+
package -> packages, ...)
|
6
|
+
* Generic package search
|
7
|
+
* Extended Patch with applicable?() and install() methods
|
8
|
+
* Added testsuites
|
9
|
+
* Packaging into gem
|
10
|
+
|
11
|
+
0.0.1 (2012-06-20)
|
12
|
+
------------------
|
13
|
+
* Initial implementation using POpen4
|
14
|
+
* Added Services and Repositories handling
|
15
|
+
* Added Packages and Packages handling
|
16
|
+
* Added documentation
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
=====================
|
3
|
+
|
4
|
+
Copyright (c) 2012 Lukas Ocilka
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
7
|
+
this software and associated documentation files (the "Software"), to deal in
|
8
|
+
the Software without restriction, including without limitation the rights to
|
9
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
10
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
11
|
+
so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,421 @@
|
|
1
|
+
# Zypper Library #
|
2
|
+
|
3
|
+
This library provides Ruby access to libzypp using the
|
4
|
+
`zypper` command.
|
5
|
+
|
6
|
+
## License ##
|
7
|
+
|
8
|
+
Distributed under the MIT license, see LICENSE file.
|
9
|
+
|
10
|
+
## Features ###
|
11
|
+
|
12
|
+
* Easy-to-use API
|
13
|
+
* Running zypper in chroot or running your system zypper over a different root directory
|
14
|
+
* Handling packages, repositories and patches
|
15
|
+
* Easy to extend
|
16
|
+
|
17
|
+
## Usage ##
|
18
|
+
|
19
|
+
Require the library
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require "zypper"
|
23
|
+
```
|
24
|
+
|
25
|
+
Initialize new access to the library methods
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
zypper = Zypper.new()
|
29
|
+
```
|
30
|
+
|
31
|
+
Add a new repository
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
zypper.repository.add(:url => 'http://example.org/new/repo', :alias => 'Repo_at_Example_Org')
|
35
|
+
```
|
36
|
+
|
37
|
+
## Public Methods ##
|
38
|
+
|
39
|
+
### Global ###
|
40
|
+
|
41
|
+
#### Constructor ###
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
zypper = Zypper.new(parameters)
|
45
|
+
# or
|
46
|
+
config = Zypper::Config.new(parameters)
|
47
|
+
zypper = Zypper.new(config)
|
48
|
+
```
|
49
|
+
|
50
|
+
All parameters are optional, using their default value if not set.
|
51
|
+
|
52
|
+
Possible parameters in hash:
|
53
|
+
* :root => '/changed-root' - defaults to '/'
|
54
|
+
* :chroot_method => 'local' (calls local zypper with changed root) or 'chroot' (calls zypper in chroot)
|
55
|
+
* :refresh_repo => true or false - default for all newly added repositories
|
56
|
+
* :auto_agree_with_licenses => true or false - default for installing packages, applying patches...
|
57
|
+
|
58
|
+
Example:
|
59
|
+
```ruby
|
60
|
+
zypper = Zypper.new(:chroot => '/some-chroot-dir', :chroot_method => 'chroot')
|
61
|
+
```
|
62
|
+
|
63
|
+
#### Zypper Output ####
|
64
|
+
|
65
|
+
These methods work after calling all API functions:
|
66
|
+
|
67
|
+
* last_message - unparsed STDOUT of the last zypper call
|
68
|
+
* last_error_message - unparsed STDERR of the last zypper call
|
69
|
+
* last_exit_status - exit code (integer) of the last zypper call
|
70
|
+
|
71
|
+
Example:
|
72
|
+
```ruby
|
73
|
+
zypper.last_message
|
74
|
+
```
|
75
|
+
|
76
|
+
#### Zypper Version ####
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
version
|
80
|
+
|
81
|
+
# returns
|
82
|
+
{:major=>1, :minor=>3, :revision=>7}
|
83
|
+
```
|
84
|
+
|
85
|
+
#### Caches Cleanup ####
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
clean_caches
|
89
|
+
|
90
|
+
# returns
|
91
|
+
true or false
|
92
|
+
```
|
93
|
+
|
94
|
+
#### Importing All used GPG Keys ####
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
auto_import_keys
|
98
|
+
|
99
|
+
# returns
|
100
|
+
true or false
|
101
|
+
```
|
102
|
+
|
103
|
+
### Repositories ###
|
104
|
+
|
105
|
+
You can access the repositories class either with
|
106
|
+
```ruby
|
107
|
+
zypper = Zypper.new
|
108
|
+
zypper.repository
|
109
|
+
# or
|
110
|
+
zypper.repositories
|
111
|
+
```
|
112
|
+
or
|
113
|
+
```ruby
|
114
|
+
Zypper::Repository.new
|
115
|
+
```
|
116
|
+
|
117
|
+
#### Listing repositories ####
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
zypper.repositories.all
|
121
|
+
|
122
|
+
# returns
|
123
|
+
[
|
124
|
+
{ "enabled"=>"1", "autorefresh"=>"1", "name"=>"SLES11-SP1-x68_64", "url"=>["http://repo/URI"],
|
125
|
+
"type"=>"rpm-md", "alias"=>"repository_alias", "gpgcheck"=>"1" },
|
126
|
+
{ ... },
|
127
|
+
...
|
128
|
+
]
|
129
|
+
```
|
130
|
+
|
131
|
+
#### Adding a Repository ####
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
zypper.repository.add(:url => 'http://repository/URI', :alias => 'repository_alias')
|
135
|
+
|
136
|
+
# returns
|
137
|
+
true or false
|
138
|
+
```
|
139
|
+
|
140
|
+
Example:
|
141
|
+
```ruby
|
142
|
+
Zypper.new.repository.add(:url => 'http://repository/URI', :alias => 'repository_alias')
|
143
|
+
# or
|
144
|
+
Zypper::Repository.new.add(:url => 'http://repository/URI', :alias => 'repository_alias')
|
145
|
+
```
|
146
|
+
|
147
|
+
#### Removing a Repository ####
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
zypper.repository.remove(:alias => 'repository_alias')
|
151
|
+
|
152
|
+
# returns
|
153
|
+
true or false
|
154
|
+
```
|
155
|
+
|
156
|
+
#### Refreshing Repositories ####
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
zypper.repository.refresh(parameters)
|
160
|
+
|
161
|
+
# returns
|
162
|
+
true or false
|
163
|
+
```
|
164
|
+
|
165
|
+
Possible optional parameters:
|
166
|
+
* :force - forces a complete refresh
|
167
|
+
* :force_build - forces rebuild of the database
|
168
|
+
|
169
|
+
### Services ###
|
170
|
+
|
171
|
+
You can access the services class either with
|
172
|
+
```ruby
|
173
|
+
zypper = Zypper.new
|
174
|
+
zypper.service
|
175
|
+
# or
|
176
|
+
zypper.services
|
177
|
+
```
|
178
|
+
or
|
179
|
+
```ruby
|
180
|
+
Zypper::Service.new
|
181
|
+
```
|
182
|
+
|
183
|
+
#### Listing Services ####
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
zypper.services.all
|
187
|
+
```
|
188
|
+
|
189
|
+
Example:
|
190
|
+
```ruby
|
191
|
+
Zypper.new.services.all
|
192
|
+
# or
|
193
|
+
Zypper::Services.new.all
|
194
|
+
```
|
195
|
+
|
196
|
+
#### Refreshing Services ####
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
zypper.services.refresh
|
200
|
+
|
201
|
+
# returns
|
202
|
+
true or false
|
203
|
+
```
|
204
|
+
|
205
|
+
### Packages ###
|
206
|
+
|
207
|
+
#### Installing Packages ####
|
208
|
+
|
209
|
+
You can access the packages class either with
|
210
|
+
```ruby
|
211
|
+
zypper = Zypper.new
|
212
|
+
zypper.package
|
213
|
+
# or
|
214
|
+
zypper.packages
|
215
|
+
```
|
216
|
+
or
|
217
|
+
```ruby
|
218
|
+
Zypper::Package.new
|
219
|
+
```
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
zypper.packages.install(:packages => ['package', 'package', ...])
|
223
|
+
|
224
|
+
# returns
|
225
|
+
true or false
|
226
|
+
```
|
227
|
+
|
228
|
+
`package` string can consist of NAME[.ARCH][OP<VERSION>], where OP is one
|
229
|
+
of <, <=, =, >=, >, for example:
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
zypper.package.install :packages => ['less.x86_64=424b-10.22']
|
233
|
+
```
|
234
|
+
|
235
|
+
#### Removing Packages ####
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
zypper.packages.remove(:packages => ['package', 'package', ...])
|
239
|
+
|
240
|
+
# returns
|
241
|
+
true or false
|
242
|
+
```
|
243
|
+
|
244
|
+
`package` string can consist of NAME[.ARCH][OP<VERSION>], where OP is one
|
245
|
+
of <, <=, =, >=, >, for example:
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
zypper.package.remove :packages => ['less.x86_64=424b-10.22']
|
249
|
+
```
|
250
|
+
|
251
|
+
#### Installed Packages ####
|
252
|
+
|
253
|
+
Lists all installed packages.
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
zypper.packages.installed
|
257
|
+
|
258
|
+
# returns
|
259
|
+
[
|
260
|
+
{
|
261
|
+
:type=>"package", :status=>:installed, :summary=>"Package, Patch, Pattern, and Product Management",
|
262
|
+
:name=>"libzypp"
|
263
|
+
},
|
264
|
+
{ ... },
|
265
|
+
...
|
266
|
+
]
|
267
|
+
```
|
268
|
+
|
269
|
+
#### Available Packages ####
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
zypper.packages.available
|
273
|
+
|
274
|
+
# returns
|
275
|
+
[
|
276
|
+
{
|
277
|
+
:type=>"package", :status=>:available, :summary=>"Helper that makes writing ...",
|
278
|
+
:name=>"zypp-plugin-python"
|
279
|
+
},
|
280
|
+
{ ... },
|
281
|
+
...
|
282
|
+
]
|
283
|
+
```
|
284
|
+
|
285
|
+
#### Packages Search ####
|
286
|
+
|
287
|
+
```ruby
|
288
|
+
zypper.packages.find
|
289
|
+
|
290
|
+
# returns
|
291
|
+
[
|
292
|
+
... list of packages ...
|
293
|
+
]
|
294
|
+
```
|
295
|
+
|
296
|
+
Example
|
297
|
+
```ruby
|
298
|
+
# All packages with name 'kernel-default'
|
299
|
+
zypper.packages.find(:name => 'kernel-default')
|
300
|
+
|
301
|
+
# All available packages matching zypp*
|
302
|
+
zypper.packages.find(:name => 'zypp*', :status => :available)
|
303
|
+
|
304
|
+
# All installed packages
|
305
|
+
zypper.packages.find(:status => :installed)
|
306
|
+
```
|
307
|
+
|
308
|
+
#### Package Info ####
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
zypper.package.info(:package => 'package')
|
312
|
+
|
313
|
+
# Returns, e.g.
|
314
|
+
{
|
315
|
+
:status=>"not installed", :version=>"424b-10.22",
|
316
|
+
:summary=>"Text File Browser and Pager Similar to more", :arch=>"x86_64",
|
317
|
+
:repository=>"SLES11-SP1-x68_64", :size=>"266.0 KiB",
|
318
|
+
:vendor=>"SUSE LINUX Products GmbH, Nuernberg, Germany",
|
319
|
+
:name=>"less", :installed=>"No", :level=>"Level 3"
|
320
|
+
}
|
321
|
+
```
|
322
|
+
|
323
|
+
#### Package Installed? ####
|
324
|
+
|
325
|
+
```ruby
|
326
|
+
zypper.package.installed?(:package => 'package')
|
327
|
+
|
328
|
+
# returns
|
329
|
+
true or false
|
330
|
+
```
|
331
|
+
|
332
|
+
### Patches ###
|
333
|
+
|
334
|
+
You can access the patches class either with
|
335
|
+
|
336
|
+
```ruby
|
337
|
+
zypper = Zypper.new
|
338
|
+
zypper.patch
|
339
|
+
# or
|
340
|
+
zypper.patches
|
341
|
+
```
|
342
|
+
or
|
343
|
+
```ruby
|
344
|
+
Zypper::patch.new
|
345
|
+
```
|
346
|
+
|
347
|
+
#### Listing Patches ####
|
348
|
+
|
349
|
+
All known patches
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
zypper.patches.all
|
353
|
+
```
|
354
|
+
|
355
|
+
#### Searching for Patches ####
|
356
|
+
|
357
|
+
```ruby
|
358
|
+
zypper.patches.find(filter_parameters)
|
359
|
+
|
360
|
+
# returns
|
361
|
+
[
|
362
|
+
{ :status=>'Needed', :category=>'Recommended', :name=>'patch-name',
|
363
|
+
:version=>'patch-version', :catalog=>"repository-name"
|
364
|
+
},
|
365
|
+
{ ... },
|
366
|
+
...
|
367
|
+
]
|
368
|
+
```
|
369
|
+
All parameters are optional and can be combined, using their default value if not set.
|
370
|
+
|
371
|
+
Possible parameters in hash:
|
372
|
+
|
373
|
+
* :status => 'Status' (see Zypper::Patch::Status class constants)
|
374
|
+
* :category => 'Category' (See Zypper::Patch::Category class constants)
|
375
|
+
* :name => 'Exact-Name'
|
376
|
+
* :version => 'Exact-Version'
|
377
|
+
* :catalog => 'Alias-of-the-repo'
|
378
|
+
|
379
|
+
Example:
|
380
|
+
```ruby
|
381
|
+
zypper.patches.all(
|
382
|
+
:status => Zypper::Patch::Status::INSTALLED,
|
383
|
+
:category => Zypper::Patch::Category::RECOMMENDED
|
384
|
+
)
|
385
|
+
```
|
386
|
+
|
387
|
+
#### Applicable Patches ####
|
388
|
+
|
389
|
+
Lists all applicable patches. All filter parameters are optional and can
|
390
|
+
be used the same as for the `find()` method.
|
391
|
+
|
392
|
+
```ruby
|
393
|
+
zypper.patches.applicable(filter_parameters)
|
394
|
+
```
|
395
|
+
|
396
|
+
#### Any Applicable Patches? ####
|
397
|
+
|
398
|
+
Returns whether there are any applicable patches present.
|
399
|
+
All filter parameters are optional and can be used the same as for the
|
400
|
+
`find()` method.
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
zypper.patches.applicable?(filter_parameters)
|
404
|
+
```
|
405
|
+
|
406
|
+
#### Installed Patches
|
407
|
+
|
408
|
+
Lists all installed patches. All filter parameters are optional and can
|
409
|
+
be used the same as for the `find()` method.
|
410
|
+
|
411
|
+
```ruby
|
412
|
+
zypper.patches.installed(filter_parameters)
|
413
|
+
```
|
414
|
+
|
415
|
+
#### Install Patches ####
|
416
|
+
|
417
|
+
Installs all applicable patches.
|
418
|
+
|
419
|
+
```ruby
|
420
|
+
zypper.patches.install
|
421
|
+
```
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/lib/zypper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'zypper/utils'
|
2
|
+
|
3
|
+
require 'zypper/repository'
|
4
|
+
require 'zypper/service'
|
5
|
+
require 'zypper/package'
|
6
|
+
require 'zypper/patch'
|
7
|
+
|
8
|
+
class Zypper
|
9
|
+
include ZypperUtils
|
10
|
+
|
11
|
+
attr_reader :repository, :service, :package, :patch
|
12
|
+
|
13
|
+
alias :repositories :repository
|
14
|
+
alias :services :service
|
15
|
+
alias :packages :package
|
16
|
+
alias :patches :patch
|
17
|
+
|
18
|
+
def initialize(params = {})
|
19
|
+
super(params)
|
20
|
+
|
21
|
+
self.repository = Zypper::Repository.new config
|
22
|
+
self.service = Zypper::Service.new config
|
23
|
+
self.package = Zypper::Package.new config
|
24
|
+
self.patch = Zypper::Patch.new config
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the current zypper version
|
28
|
+
def version(options = {})
|
29
|
+
if (run(build_command('version', options = {})))
|
30
|
+
version_number(last_message, options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Cleans the libzypp cache
|
35
|
+
def clean_caches(options = {})
|
36
|
+
run build_command('clean', options)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Auto-imports all GPG keys from repositories
|
40
|
+
def auto_import_keys(options = {})
|
41
|
+
previous_auto_import_gpg = config.auto_import_gpg
|
42
|
+
ret = repositories.refresh
|
43
|
+
config.auto_import_gpg = previous_auto_import_gpg
|
44
|
+
ret
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_writer :repository, :service, :package, :patch
|
50
|
+
|
51
|
+
def version_number(version_string, options)
|
52
|
+
version = version_string.gsub(/[^0-9\.]/, '').split('.')
|
53
|
+
{:major => version[0].to_i, :minor => version[1].to_i, :revision => version[2].to_i}
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class Zypper
|
5
|
+
class Config
|
6
|
+
|
7
|
+
DEFAULT_ROOT = '/'
|
8
|
+
DEFAULT_IMPORT_GPG = true
|
9
|
+
DEFAULT_REFRESH_REPO = true
|
10
|
+
DEFAULT_AUTO_AGREE_WITH_LICENSES = true
|
11
|
+
DEFAULT_CHROOT_METHOD = 'local'
|
12
|
+
|
13
|
+
CHROOT_METHOD_LOCAL = 'local'
|
14
|
+
CHROOT_METHOD_CHROOT = 'chroot'
|
15
|
+
KNOWN_CHROOT_METHODS = [CHROOT_METHOD_LOCAL, CHROOT_METHOD_CHROOT]
|
16
|
+
|
17
|
+
# Constructor
|
18
|
+
#
|
19
|
+
# Possible parameters
|
20
|
+
# (string) :root
|
21
|
+
# Defines the changed root environment, default '/'
|
22
|
+
# (boolean) :auto_import_gpg
|
23
|
+
# Automatically trust (and import) new GPG keys, default true
|
24
|
+
# (boolean) :refresh_repo
|
25
|
+
# Adds new repositories with autorefresh flag, default true
|
26
|
+
# (string) :chroot_method
|
27
|
+
# Defines which zypper is used; 'local' uses the local zypper with
|
28
|
+
# changed root directory specified as --root parameter whereas
|
29
|
+
# 'chroot' uses chroot binary and calls zypper directly in the
|
30
|
+
# :root directory. This can be ignored if changed :root is not
|
31
|
+
# defined
|
32
|
+
# (boolean :auto_agree_with_licenses
|
33
|
+
# automatically accept all licenses, otherwise such packages
|
34
|
+
# cannot be installed
|
35
|
+
def initialize(params = {})
|
36
|
+
self.root = (params[:root] || DEFAULT_ROOT)
|
37
|
+
self.chroot_method = (params[:chroot_method] || DEFAULT_CHROOT_METHOD)
|
38
|
+
|
39
|
+
@auto_import_gpg = (params[:auto_import_gpg] || DEFAULT_IMPORT_GPG)
|
40
|
+
@refresh_repo = (params[:refresh_repo] || DEFAULT_REFRESH_REPO)
|
41
|
+
@auto_agree_with_licenses = (params[:auto_agree_with_licenses] || DEFAULT_AUTO_AGREE_WITH_LICENSES)
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_accessor :auto_import_gpg
|
45
|
+
|
46
|
+
attr_reader :root, :chroot_method
|
47
|
+
|
48
|
+
# Changes the current root directory, the directory must exist
|
49
|
+
def root=(new_root)
|
50
|
+
if ! File.exists? new_root
|
51
|
+
raise "Directory #{new_root} does not exist"
|
52
|
+
elsif ! File.directory? new_root
|
53
|
+
raise "#{new_root} is not a directory"
|
54
|
+
end
|
55
|
+
|
56
|
+
@root = new_root
|
57
|
+
end
|
58
|
+
|
59
|
+
# Changes the current chroot method, see constructor for possible values
|
60
|
+
def chroot_method=(new_chroot_method)
|
61
|
+
unless KNOWN_CHROOT_METHODS.include? new_chroot_method
|
62
|
+
raise "Unknown chroot method #{new_chroot_method}, possible are #{KNOWN_CHROOT_METHODS.join(', ')}"
|
63
|
+
end
|
64
|
+
|
65
|
+
@chroot_method = new_chroot_method
|
66
|
+
end
|
67
|
+
|
68
|
+
# Using chroot command
|
69
|
+
def chrooted?
|
70
|
+
chroot_method == CHROOT_METHOD_CHROOT
|
71
|
+
end
|
72
|
+
|
73
|
+
# Using zypper --root of the root is actually different
|
74
|
+
def changed_root?
|
75
|
+
root != DEFAULT_ROOT && chroot_method == CHROOT_METHOD_LOCAL
|
76
|
+
end
|
77
|
+
|
78
|
+
def auto_import_gpg?
|
79
|
+
@auto_import_gpg
|
80
|
+
end
|
81
|
+
|
82
|
+
def auto_agree_with_licenses?
|
83
|
+
@auto_agree_with_licenses
|
84
|
+
end
|
85
|
+
|
86
|
+
def refresh_repo?
|
87
|
+
@refresh_repo
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'zypper/utils'
|
2
|
+
|
3
|
+
class Zypper
|
4
|
+
class Package
|
5
|
+
include ZypperUtils
|
6
|
+
|
7
|
+
class Status
|
8
|
+
INSTALLED = :installed
|
9
|
+
AVAILABLE = :uninstalled
|
10
|
+
end
|
11
|
+
|
12
|
+
PACKAGE_STATUSES = {
|
13
|
+
'' => Status::AVAILABLE,
|
14
|
+
'i' => Status::INSTALLED,
|
15
|
+
}
|
16
|
+
|
17
|
+
# Installs packages given as parmeter
|
18
|
+
# (array) :packages
|
19
|
+
def install(options = {})
|
20
|
+
run build_command('install', options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Removes packages given as parmeter
|
24
|
+
# (array) :packages
|
25
|
+
def remove(options = {})
|
26
|
+
run build_command('remove', options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns hash of information on a package given as parameter
|
30
|
+
# (string) :package
|
31
|
+
def info(options = {})
|
32
|
+
if (run(build_command('info', options)))
|
33
|
+
convert_info(last_message)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# returns whether a package given as parameter is installed
|
38
|
+
# (string) :package
|
39
|
+
def installed?(options = {})
|
40
|
+
info(options).fetch(Status::INSTALLED, 'No') == 'Yes'
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns packages found using given parameters
|
44
|
+
#
|
45
|
+
# @param (Hash) of options
|
46
|
+
# (string) :name - exact name of a package
|
47
|
+
# (symbol) :status - See Zypper::Package::Status class constants
|
48
|
+
def find(options = {})
|
49
|
+
additional_options = {:cmd_options => ['--type package'], :quiet => true}
|
50
|
+
|
51
|
+
if (run (build_command('search', options.merge(additional_options))))
|
52
|
+
convert_packages(last_message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns all installed packages
|
57
|
+
def installed(options = {})
|
58
|
+
find(options.merge(:status => Status::INSTALLED))
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns all available packages (that are not installed yet)
|
62
|
+
def available(options = {})
|
63
|
+
find(options.merge(:status => Status::AVAILABLE))
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def status(status)
|
69
|
+
return PACKAGE_STATUSES[status] if PACKAGE_STATUSES[status]
|
70
|
+
|
71
|
+
raise "Unknown package status '#{status}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
# SLE11 zypper doesn't support XML output for packages
|
75
|
+
# FIXME: merge with 'convert_patches'
|
76
|
+
def convert_packages(packages)
|
77
|
+
out = []
|
78
|
+
table_index = 0
|
79
|
+
package = {}
|
80
|
+
|
81
|
+
packages.split("\n").each {|line|
|
82
|
+
table_index = table_index + 1
|
83
|
+
# Skip the first two - table header
|
84
|
+
next if table_index < 3
|
85
|
+
|
86
|
+
line.gsub!(/ +\| +/, '|')
|
87
|
+
line.gsub!(/^ +/, '')
|
88
|
+
line.gsub!(/ +$/, '')
|
89
|
+
package = line.split '|'
|
90
|
+
|
91
|
+
out.push(
|
92
|
+
:status => status(package[0]),
|
93
|
+
:name => package[1],
|
94
|
+
:summary => package[2],
|
95
|
+
:type => package[3]
|
96
|
+
)
|
97
|
+
}
|
98
|
+
|
99
|
+
out
|
100
|
+
end
|
101
|
+
|
102
|
+
def convert_info(info)
|
103
|
+
out = {}
|
104
|
+
|
105
|
+
info.split("\n").each do |line|
|
106
|
+
if /([[:alnum:]]+): (.+)/.match(line)
|
107
|
+
out[$1.downcase.to_sym] = $2
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
out
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
data/lib/zypper/patch.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'zypper/utils'
|
2
|
+
|
3
|
+
class Zypper
|
4
|
+
class Patch
|
5
|
+
class Status
|
6
|
+
NEEDED = 'Needed'
|
7
|
+
INSTALLED = 'Installed'
|
8
|
+
NOT_APPLICABLE = 'Not Applicable'
|
9
|
+
end
|
10
|
+
|
11
|
+
class Category
|
12
|
+
SECURITY = 'security'
|
13
|
+
RECOMMENDED = 'recommended'
|
14
|
+
FEATURE = 'feature'
|
15
|
+
OPTIONAL = 'optional'
|
16
|
+
end
|
17
|
+
|
18
|
+
include ZypperUtils
|
19
|
+
|
20
|
+
FILTER_OPTIONS = [:repository, :name, :version, :category, :status]
|
21
|
+
|
22
|
+
# Lists all patches
|
23
|
+
#
|
24
|
+
# @param Hash with optional key :where (Hash)
|
25
|
+
# that can consist of one or more parameters from
|
26
|
+
# :repository, :name, :version, :category, and :status.
|
27
|
+
# Logical AND is always applied for all the options present
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# all(:status => 'Installed')
|
31
|
+
def find(options = {})
|
32
|
+
additional_options = {:quiet => true}
|
33
|
+
|
34
|
+
if (run(build_command('patches', options.merge(additional_options))))
|
35
|
+
apply_filters(convert_patches(last_message), options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Lists all known patches
|
40
|
+
def all(options = {})
|
41
|
+
find
|
42
|
+
end
|
43
|
+
|
44
|
+
# All applicable patches
|
45
|
+
def applicable(options = {})
|
46
|
+
find(options.merge(:status => Status::NEEDED))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Are there any applicable patches present?
|
50
|
+
def applicable?(options = {})
|
51
|
+
applicable(options).size > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
# Installs all applicable patches
|
55
|
+
def install(options = {})
|
56
|
+
|
57
|
+
run(build_command('patch', options))
|
58
|
+
end
|
59
|
+
|
60
|
+
# All installed patches
|
61
|
+
def installed(options = {})
|
62
|
+
find(options.merge(:status => Status::INSTALLED))
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Current libzypp doesn't support XML output for patches
|
68
|
+
def convert_patches(patches)
|
69
|
+
out = []
|
70
|
+
table_index = 0
|
71
|
+
patch = {}
|
72
|
+
|
73
|
+
patches.split("\n").each {|line|
|
74
|
+
table_index = table_index + 1
|
75
|
+
# Skip the first two - table header
|
76
|
+
next if table_index < 3
|
77
|
+
|
78
|
+
line.gsub!(/ +\| +/, '|')
|
79
|
+
line.gsub!(/^ +/, '')
|
80
|
+
line.gsub!(/ +$/, '')
|
81
|
+
patch = line.split '|'
|
82
|
+
|
83
|
+
out.push(
|
84
|
+
:repository => patch[0],
|
85
|
+
:name => patch[1],
|
86
|
+
:version => patch[2],
|
87
|
+
:category => patch[3],
|
88
|
+
:status => patch[4]
|
89
|
+
)
|
90
|
+
}
|
91
|
+
|
92
|
+
out
|
93
|
+
end
|
94
|
+
|
95
|
+
# Filters patches according to given parameters
|
96
|
+
#
|
97
|
+
# @param (Array) patches
|
98
|
+
# @param (Hash) filters criteria, possible keys are :repository, :name, :version, :category and :status
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# apply_patch_filters(patches, { :status => 'Needed' })
|
102
|
+
# apply_patch_filters(patches, { :version' => '1887', :repository => 'SLES11-SP1-Update' })
|
103
|
+
def apply_filters(patches = [], filters = {})
|
104
|
+
filters.each {|filter_key, filter_value|
|
105
|
+
raise "Unknown filter parameter '#{filter_key}'" unless FILTER_OPTIONS.include? filter_key
|
106
|
+
|
107
|
+
patches = patches.select{|patch| patch[filter_key] == filter_value}
|
108
|
+
}
|
109
|
+
patches
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'zypper/utils'
|
2
|
+
|
3
|
+
class Zypper
|
4
|
+
class Repository
|
5
|
+
include ZypperUtils
|
6
|
+
|
7
|
+
# Refreshes repositories
|
8
|
+
# @param (optional) options
|
9
|
+
# :force - to force the refresh
|
10
|
+
# :force_rebuild - forces rebuilding the libzypp database
|
11
|
+
def refresh(options = {})
|
12
|
+
run build_command('refresh', options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Lists all known repositories
|
16
|
+
def all(options = {})
|
17
|
+
out = xml_run build_command('repos', options.merge(:get => XML_COMMANDS_GET))
|
18
|
+
out.fetch('repo-list', []).fetch(0, {}).fetch('repo', [])
|
19
|
+
end
|
20
|
+
|
21
|
+
# Adds a new repository defined by options
|
22
|
+
# (string) :url URL/URL
|
23
|
+
# (string) :alias
|
24
|
+
def add(options = {})
|
25
|
+
run build_command('addrepo', options)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Removes a repository defined by options
|
29
|
+
# (string) :alias
|
30
|
+
def remove(options = {})
|
31
|
+
run build_command('removerepo', options)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'zypper/utils'
|
2
|
+
|
3
|
+
class Zypper
|
4
|
+
class Service
|
5
|
+
include ZypperUtils
|
6
|
+
|
7
|
+
# Refreshes services
|
8
|
+
def refresh(options = {})
|
9
|
+
run build_command('refresh-services', options)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Lists all known services
|
13
|
+
def all(options = {})
|
14
|
+
out = xml_run build_command('services', options.merge(:get => XML_COMMANDS_GET))
|
15
|
+
out.fetch('service-list', []).fetch(0, {}).fetch('service', [])
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/zypper/utils.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
module ZypperUtils
|
2
|
+
require 'rubygems'
|
3
|
+
require 'shellwords'
|
4
|
+
require 'popen4'
|
5
|
+
require 'xmlsimple'
|
6
|
+
|
7
|
+
require 'zypper/config'
|
8
|
+
|
9
|
+
XML_COMMANDS_GET = 'xml'
|
10
|
+
|
11
|
+
# Only getters are public
|
12
|
+
attr_reader :last_message, :last_error_message, :last_exit_status, :config
|
13
|
+
|
14
|
+
# Constructor
|
15
|
+
#
|
16
|
+
# @param either instance of Zypper::Config class
|
17
|
+
# or hash of options for new Zypper::Config class
|
18
|
+
#
|
19
|
+
# See Zypper::Config new() for more info
|
20
|
+
def initialize(params = {})
|
21
|
+
# Config is the given parameter
|
22
|
+
if (params.instance_of?(Zypper::Config))
|
23
|
+
self.config = params
|
24
|
+
# Called directly
|
25
|
+
elsif (params.is_a?(Hash))
|
26
|
+
self.config = Zypper::Config.new params
|
27
|
+
# Unknown call method
|
28
|
+
else
|
29
|
+
raise "Parameters #{params.inspect} is neither Zypper::Config nor Hash with options"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Setters are private
|
36
|
+
attr_writer :last_message, :last_error_message, :last_exit_status, :config
|
37
|
+
|
38
|
+
def check_mandatory_options_set(zypper_action, options, mandatory)
|
39
|
+
mandatory.each {|option|
|
40
|
+
raise "Missing '#{option}' parameter in '#{zypper_action}' action" if options[option].nil?
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_mandatory_options(zypper_action, options)
|
45
|
+
case zypper_action
|
46
|
+
when 'addrepo'
|
47
|
+
check_mandatory_options_set(zypper_action, options, [:url, :alias])
|
48
|
+
# FIXME: check that :url or :alias do not contain any spaces (or special characters)
|
49
|
+
when 'removerepo'
|
50
|
+
check_mandatory_options_set(zypper_action, options, [:alias])
|
51
|
+
# FIXME: check that :url or :alias do not contain any spaces (or special characters)
|
52
|
+
when 'install'
|
53
|
+
# FIXME: check that :packages do not contain any spaces (or special characters)
|
54
|
+
check_mandatory_options_set(zypper_action, options, [:packages])
|
55
|
+
when 'remove'
|
56
|
+
# FIXME: check that :packages do not contain any spaces (or special characters)
|
57
|
+
check_mandatory_options_set(zypper_action, options, [:packages])
|
58
|
+
when 'info'
|
59
|
+
# FIXME: check that :package does not contain any spaces (or special characters)
|
60
|
+
check_mandatory_options_set(zypper_action, options, [:package])
|
61
|
+
# No checks:
|
62
|
+
# * 'search' used also just with command-line parameters but no particular
|
63
|
+
# object to search for
|
64
|
+
#
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def chrooted
|
69
|
+
config.chrooted? ? 'chroot ' + Shellwords::escape(config.root) + ' ' : ''
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the full zypper command including chroot, zypper command, options, etc.
|
73
|
+
def build_command(zypper_action, options = {})
|
74
|
+
check_mandatory_options(zypper_action, options)
|
75
|
+
|
76
|
+
chrooted + ' zypper ' + global_options(options) + ' ' +
|
77
|
+
zypper_command(zypper_action) + ' ' + zypper_command_options(zypper_action, options)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a zypper command (shell) defined by an action
|
81
|
+
def zypper_command zypper_action
|
82
|
+
case zypper_action
|
83
|
+
# version is a global option but not a command
|
84
|
+
when 'version'
|
85
|
+
''
|
86
|
+
else
|
87
|
+
zypper_action
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def escape_items(items = [])
|
92
|
+
items.collect{|package| Shellwords::escape(package)}.join(' ')
|
93
|
+
end
|
94
|
+
|
95
|
+
def escape(item = '')
|
96
|
+
Shellwords::escape(item)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns string of command options depending on a given zypper command
|
100
|
+
# combined with provided options
|
101
|
+
def zypper_command_options(zypper_action, options = {})
|
102
|
+
ret_options = []
|
103
|
+
|
104
|
+
# Additional command-line options for a command
|
105
|
+
if options[:cmd_options]
|
106
|
+
ret_options = options[:cmd_options]
|
107
|
+
end
|
108
|
+
|
109
|
+
case zypper_action
|
110
|
+
when 'refresh'
|
111
|
+
ret_options = [
|
112
|
+
options[:force] ? '--force' : '',
|
113
|
+
options[:force_build] ? '--force-build' : '',
|
114
|
+
]
|
115
|
+
when 'addrepo'
|
116
|
+
ret_options = [
|
117
|
+
config.refresh_repo? ? '--refresh':'',
|
118
|
+
options[:url],
|
119
|
+
options[:alias],
|
120
|
+
]
|
121
|
+
when 'removerepo'
|
122
|
+
ret_options = [
|
123
|
+
options[:alias],
|
124
|
+
]
|
125
|
+
when 'install'
|
126
|
+
ret_options = [
|
127
|
+
config.auto_agree_with_licenses? ? '--auto-agree-with-licenses' : '',
|
128
|
+
escape_items(options[:packages]),
|
129
|
+
]
|
130
|
+
when 'remove'
|
131
|
+
ret_options = [
|
132
|
+
escape_items(options[:packages]),
|
133
|
+
]
|
134
|
+
when 'version'
|
135
|
+
ret_options = [
|
136
|
+
'--version',
|
137
|
+
]
|
138
|
+
when 'info'
|
139
|
+
ret_options = [
|
140
|
+
escape(options[:package]),
|
141
|
+
]
|
142
|
+
when 'search'
|
143
|
+
ret_options = [
|
144
|
+
options[:status] == Zypper::Package::Status::INSTALLED ? '--installed-only' : '',
|
145
|
+
options[:status] == Zypper::Package::Status::AVAILABLE ? '--uninstalled-only' : '',
|
146
|
+
|
147
|
+
options[:name] ? '--match-exact ' + escape(options[:name]) : '',
|
148
|
+
]
|
149
|
+
end
|
150
|
+
|
151
|
+
ret_options.join(' ')
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns string with global zypper options
|
155
|
+
def global_options(options = {})
|
156
|
+
[
|
157
|
+
(options[:quiet] ? '--quiet' : ''),
|
158
|
+
(config.changed_root? ? '--root=' + Shellwords::escape(config.root) : ''),
|
159
|
+
(options[:get] == XML_COMMANDS_GET ? '--xmlout' : ''),
|
160
|
+
'--non-interactive',
|
161
|
+
(config.auto_import_gpg? ? '--gpg-auto-import-keys' : ''),
|
162
|
+
].join(' ')
|
163
|
+
end
|
164
|
+
|
165
|
+
def xml_run(command)
|
166
|
+
xml = run(command, {:get => XML_COMMANDS_GET})
|
167
|
+
out = XmlSimple.xml_in(xml)
|
168
|
+
|
169
|
+
if !out["message"].nil?
|
170
|
+
errors = out["message"].select{|hash| hash["type"] == "error"}
|
171
|
+
self.last_error = errors.collect{|hash| hash["content"]}.join("\n")
|
172
|
+
end
|
173
|
+
|
174
|
+
out
|
175
|
+
end
|
176
|
+
|
177
|
+
# Runs a command given as argument and returns the full output
|
178
|
+
# Exit status can be acquired using last_exit_status call
|
179
|
+
def run(command, params = {})
|
180
|
+
# FIXME: it's here just for debugging
|
181
|
+
puts "DEBUG: " + command
|
182
|
+
|
183
|
+
cmd_ret = POpen4::popen4(command) do |stdout, stderr, stdin, pid|
|
184
|
+
self.last_message = stdout.read.strip
|
185
|
+
self.last_error_message = stderr.read.strip
|
186
|
+
end
|
187
|
+
|
188
|
+
last_exit_status = cmd_ret.exitstatus
|
189
|
+
|
190
|
+
if params[:get] == XML_COMMANDS_GET
|
191
|
+
last_message
|
192
|
+
else
|
193
|
+
last_exit_status == 0
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zypper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Lukas Ocilka
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-06-26 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: popen4
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: xml-simple
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: mocha
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
description: |-
|
77
|
+
Library for accessing zypper functions such as searching and
|
78
|
+
installing packages, adding and removing repositories and services. Supports
|
79
|
+
calling zypper in changed root (both with local zypper and zypper in chroot).
|
80
|
+
email: lukas.ocilka@gmail.com
|
81
|
+
executables: []
|
82
|
+
|
83
|
+
extensions: []
|
84
|
+
|
85
|
+
extra_rdoc_files: []
|
86
|
+
|
87
|
+
files:
|
88
|
+
- lib/zypper.rb
|
89
|
+
- lib/zypper/config.rb
|
90
|
+
- lib/zypper/repository.rb
|
91
|
+
- lib/zypper/utils.rb
|
92
|
+
- lib/zypper/package.rb
|
93
|
+
- lib/zypper/patch.rb
|
94
|
+
- lib/zypper/service.rb
|
95
|
+
- lib/zypper/version.rb
|
96
|
+
- LICENSE
|
97
|
+
- CHANGELOG
|
98
|
+
- README.markdown
|
99
|
+
- VERSION
|
100
|
+
homepage: https://github.com/kobliha/zypper
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
hash: 3
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
hash: 3
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
requirements: []
|
127
|
+
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 1.8.15
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: Library for accessing zypper
|
133
|
+
test_files: []
|
134
|
+
|
135
|
+
has_rdoc:
|