itamae-plugin-resource-portage 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +96 -0
- data/Rakefile +6 -0
- data/itamae-plugin-resource-portage.gemspec +26 -0
- data/lib/itamae-plugin-resource-portage.rb +3 -0
- data/lib/itamae-plugin-resource-portage/portage_file_resource_base.rb +162 -0
- data/lib/itamae-plugin-resource-portage/resource_base.rb +53 -0
- data/lib/itamae-plugin-resource-portage/resources.rb +13 -0
- data/lib/itamae-plugin-resource-portage/resources/portage.rb +157 -0
- data/lib/itamae-plugin-resource-portage/resources/portage_accept_keywords.rb +24 -0
- data/lib/itamae-plugin-resource-portage/resources/portage_mask.rb +15 -0
- data/lib/itamae-plugin-resource-portage/resources/portage_package.rb +138 -0
- data/lib/itamae-plugin-resource-portage/resources/portage_pin.rb +37 -0
- data/lib/itamae-plugin-resource-portage/resources/portage_unmask.rb +15 -0
- data/lib/itamae-plugin-resource-portage/resources/portage_use.rb +17 -0
- data/lib/itamae-plugin-resource-portage/version.rb +3 -0
- data/lib/itamae/plugin/resource/portage.rb +9 -0
- data/script/console +14 -0
- data/script/setup +7 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6934173b643af32c0be76926c4b63be912edb7be
|
4
|
+
data.tar.gz: 5e966d20c26bf0d127baaf7c0c4a74e3c875df6a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd3c0fc6d72224171c4a393cba286a036b3af539cd827cace9ddc474d1ec7ff77b9afa874975d70e653a90c29bf0bf4f4ebff4839b4303b29c437b52803a4a30
|
7
|
+
data.tar.gz: 4b5fb91c5858da0a0ef50d234de605edc470d871d6a9830b1c0606248ab9a024b20fe1cb2459a884dace3a9990faf8ed2390320488dee0dc261417050f79438f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Shota Fukumori (sora_h)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Itamae::Plugin::Resource::Portage
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
gem 'itamae-plugin-resource-portage'
|
7
|
+
```
|
8
|
+
|
9
|
+
## prerequisites
|
10
|
+
|
11
|
+
- eix
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### Basic attributes
|
16
|
+
|
17
|
+
All resources take `name`, `slot`, `version`, and/or `atom` attribtues
|
18
|
+
|
19
|
+
- name (default_name): package name (category/name)
|
20
|
+
- version (+ slot) or atom:
|
21
|
+
- version: package version + operator (e.g. `1.0.0`, `>=1.0.0`, `<2.0.0`)
|
22
|
+
- slot: (optional)
|
23
|
+
- atom: if specified, version and slot are ignored
|
24
|
+
|
25
|
+
`portage_accept_keywords`, `portage_mask`, `portage_unmask`, `portage_use` resource take additionally:
|
26
|
+
|
27
|
+
- action: `:add` (default) or `:remove`
|
28
|
+
- target: when absolute path given, the resource will use that path to modify (e.g. `/etc/portage/package.use/foobar`). Otherwise, given name under appropriate directory will be used (e.g. `foobar` to `/etc/portage/package.XXX/foobar`); Default to `/etc/portage/package.XXX/itamae` or `/etc/portage/package.XXX` (only when it exists as file)
|
29
|
+
|
30
|
+
|
31
|
+
### `portage` resource
|
32
|
+
|
33
|
+
`portage` resource defines `portage_package`, `portage_unmask`, `portage_accept_keywords`, `portage_use`, and/or `portage_pin` resources based on given attributes.
|
34
|
+
|
35
|
+
```
|
36
|
+
portage "www-servers/nginx" do
|
37
|
+
end
|
38
|
+
|
39
|
+
portage "www-servers/nginx" do
|
40
|
+
version "1.9.7"
|
41
|
+
|
42
|
+
flags ['nginx_modules_http_stub_status']
|
43
|
+
|
44
|
+
# accept keywords by default, but if you want to disable:
|
45
|
+
# keywords []
|
46
|
+
|
47
|
+
# Mask =version and unmask !=version
|
48
|
+
pin true
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
- action: install (default), remove
|
53
|
+
- unmask (nil/bool):
|
54
|
+
- pin (bool):
|
55
|
+
- noreplace (bool, default=true):
|
56
|
+
- oneshot (bool, default=false):
|
57
|
+
- flags (array)
|
58
|
+
- keywords (array,default=[$ARCH])
|
59
|
+
- package_use_file
|
60
|
+
- package_mask_file
|
61
|
+
- package_unmask_file
|
62
|
+
- package_accept_keywords_file
|
63
|
+
- emerge_cmd:
|
64
|
+
- eix_cmd:
|
65
|
+
|
66
|
+
### `portage_accept_keywords` resource
|
67
|
+
|
68
|
+
```
|
69
|
+
portage_accept_keywords "www-servers/nginx" do
|
70
|
+
keywords ['~amd64']
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
- `keywords`: Default to `$ARCH` (`eix --print ARCH`)
|
75
|
+
|
76
|
+
### `portage_mask` resource
|
77
|
+
|
78
|
+
### `portage_pin` resource
|
79
|
+
|
80
|
+
### `portage_package` resource
|
81
|
+
|
82
|
+
## Development
|
83
|
+
|
84
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
85
|
+
|
86
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/itamae-plugin-resource-portage.
|
91
|
+
|
92
|
+
|
93
|
+
## License
|
94
|
+
|
95
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
96
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'itamae-plugin-resource-portage/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "itamae-plugin-resource-portage"
|
8
|
+
spec.version = ItamaePluginResourcePortage::VERSION
|
9
|
+
spec.authors = ["sorah (Shota Fukumori)"]
|
10
|
+
spec.email = ["her@sorah.jp"]
|
11
|
+
|
12
|
+
spec.summary = %q{Itamae resources for Gentoo Portage}
|
13
|
+
spec.homepage = "https://github.com/sorah/itamae-plugin-resource-portage"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "bin"
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "itamae"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/resource_base'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
class PortageFileResourceBase < ResourceBase
|
5
|
+
define_attribute :action, default: :add
|
6
|
+
define_attribute :target, type: String
|
7
|
+
|
8
|
+
def value
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def item_list?
|
13
|
+
!(value == true || value == false)
|
14
|
+
end
|
15
|
+
|
16
|
+
def pre_action
|
17
|
+
case @current_action
|
18
|
+
when :add
|
19
|
+
attributes.value = value || (item_list? ? [] : false)
|
20
|
+
when :remove
|
21
|
+
attributes.value = item_list? ? [] : false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def action_add(options)
|
26
|
+
lines = current_content.lines.map(&:chomp)
|
27
|
+
new_line = if item_list?
|
28
|
+
"#{atom} #{value.kind_of?(Array) ? value.join(' ') : value}"
|
29
|
+
else
|
30
|
+
atom.to_s
|
31
|
+
end
|
32
|
+
modified = false
|
33
|
+
|
34
|
+
if current_value
|
35
|
+
if lines.grep(target_line_pattern).size > 1
|
36
|
+
modified = true
|
37
|
+
lines.reject! { |_| target_line_pattern === _ }
|
38
|
+
lines << new_line
|
39
|
+
else
|
40
|
+
lines.map! do |_|
|
41
|
+
if target_line_pattern === _
|
42
|
+
if _.chomp != new_line
|
43
|
+
modified = true
|
44
|
+
end
|
45
|
+
new_line
|
46
|
+
else
|
47
|
+
_
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
modified = true
|
53
|
+
lines << new_line
|
54
|
+
end
|
55
|
+
|
56
|
+
if modified
|
57
|
+
send_file(lines.join(?\n))
|
58
|
+
updated!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def action_remove(options)
|
63
|
+
lines = current_content.lines.map(&:chomp)
|
64
|
+
|
65
|
+
new_lines = lines.reject { |_| target_line_pattern === _ }
|
66
|
+
if lines.size != new_lines.size
|
67
|
+
send_file(new_lines.join(?\n))
|
68
|
+
updated!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def send_file(content)
|
73
|
+
ensure_target_directory
|
74
|
+
|
75
|
+
tempfile = Tempfile.new('portage_file')
|
76
|
+
tempfile.puts content
|
77
|
+
tempfile.flush
|
78
|
+
|
79
|
+
remote_temppath = ::File.join(runner.tmpdir, "#{self.class.name.split('::').last}-#{Time.now.to_f.to_s}")
|
80
|
+
backend.send_file(tempfile.path, remote_temppath)
|
81
|
+
run_specinfra(:change_file_mode, remote_temppath, '0644')
|
82
|
+
run_specinfra(:move_file, remote_temppath, target)
|
83
|
+
ensure
|
84
|
+
tempfile.close if tempfile
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_current_attributes
|
88
|
+
current.value = current_value
|
89
|
+
end
|
90
|
+
|
91
|
+
def clear_current_attributes
|
92
|
+
super
|
93
|
+
@current_content = nil
|
94
|
+
@current_value = nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def current_content
|
98
|
+
@current_content ||= target_exist? ? backend.receive_file(target) : "\n"
|
99
|
+
end
|
100
|
+
|
101
|
+
def current_value
|
102
|
+
@current_value = begin
|
103
|
+
lines = current_content.each_line.grep(target_line_pattern)
|
104
|
+
|
105
|
+
# https://github.com/gentoo/portage/blob/1eb8e1e38c410a6b3792d005da7a75a87c811721/pym/portage/util/__init__.py
|
106
|
+
if item_list?
|
107
|
+
if lines.empty?
|
108
|
+
nil
|
109
|
+
else
|
110
|
+
lines.flat_map { |_| _.chomp.split(/\s+/, 2)[1].split(/\s+/) }
|
111
|
+
end
|
112
|
+
else
|
113
|
+
!lines.empty?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def target_default_directory
|
119
|
+
raise NotImplementedError
|
120
|
+
end
|
121
|
+
|
122
|
+
def ensure_target_directory
|
123
|
+
target
|
124
|
+
if @target_dir_unexist
|
125
|
+
run_command(['mkdir', '-p', target_default_directory])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def target_line_pattern
|
130
|
+
item_list? ? /^#{Regexp.escape(atom)}\s/ : /^#{Regexp.escape(atom)}$/
|
131
|
+
end
|
132
|
+
|
133
|
+
def target_exist?
|
134
|
+
run_command(['test', '-e', target], error: false).exit_status == 0
|
135
|
+
end
|
136
|
+
|
137
|
+
def target
|
138
|
+
@target ||= begin
|
139
|
+
@target_dir_unexist = false
|
140
|
+
if attributes.target && attributes.target.start_with?('/') # absolute path
|
141
|
+
attributes.target
|
142
|
+
else # relative
|
143
|
+
stat = run_command(['stat', '-c', '%F' , target_default_directory], error: false)
|
144
|
+
exist = stat.exit_status.zero?
|
145
|
+
directory = exist && stat.stdout.chomp == 'directory'
|
146
|
+
file = exist && stat.stdout.chomp == 'regular file'
|
147
|
+
|
148
|
+
case
|
149
|
+
when directory
|
150
|
+
"#{target_default_directory}/#{attributes.target || 'itamae'}"
|
151
|
+
when file
|
152
|
+
target_default_directory
|
153
|
+
else # enoent
|
154
|
+
@target_dir_unexist = true
|
155
|
+
"#{target_default_directory}/#{attributes.target || 'itamae'}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'itamae'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
class ResourceBase < Itamae::Resource::Base
|
5
|
+
module Attributes
|
6
|
+
def self.included(klass)
|
7
|
+
klass.instance_eval do
|
8
|
+
define_attribute :name, type: String, default_name: true
|
9
|
+
|
10
|
+
define_attribute :version, type: String
|
11
|
+
define_attribute :slot, type: String
|
12
|
+
define_attribute :atom, type: String
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
include Attributes
|
18
|
+
|
19
|
+
def atom
|
20
|
+
@atom ||= attributes.atom or begin
|
21
|
+
case
|
22
|
+
when attributes.version
|
23
|
+
_, op, version, slot = attributes.version.match(/\A(!=|>=|>|=|<=|<|~)?(.+)(:.+)?\z/).to_a
|
24
|
+
|
25
|
+
# XXX:
|
26
|
+
if slot.nil? || slot.empty?
|
27
|
+
if attributes.slot
|
28
|
+
slot = ":#{attributes.slot}"
|
29
|
+
end
|
30
|
+
else
|
31
|
+
attributes.slot = slot[1..-1]
|
32
|
+
end
|
33
|
+
|
34
|
+
if op.nil? || op.empty?
|
35
|
+
op = '='
|
36
|
+
end
|
37
|
+
@op = op
|
38
|
+
|
39
|
+
"#{op}#{attributes.name}-#{version}#{slot}"
|
40
|
+
when attributes.name
|
41
|
+
@op = nil
|
42
|
+
attributes.name
|
43
|
+
else
|
44
|
+
raise ArgumentError, "Can't determine atom"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def atom_op
|
50
|
+
atom; @op
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/resource_base'
|
2
|
+
|
3
|
+
require 'itamae-plugin-resource-portage/portage_file_resource_base'
|
4
|
+
require 'itamae-plugin-resource-portage/resources/portage_use'
|
5
|
+
require 'itamae-plugin-resource-portage/resources/portage_accept_keywords'
|
6
|
+
require 'itamae-plugin-resource-portage/resources/portage_mask'
|
7
|
+
require 'itamae-plugin-resource-portage/resources/portage_unmask'
|
8
|
+
require 'itamae-plugin-resource-portage/resources/portage_pin'
|
9
|
+
# require 'itamae-plugin-resource-portage/resources/portage_env'
|
10
|
+
|
11
|
+
require 'itamae-plugin-resource-portage/resources/portage_package'
|
12
|
+
|
13
|
+
require 'itamae-plugin-resource-portage/resources/portage'
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'itamae/resource/base'
|
2
|
+
require 'itamae-plugin-resource-portage/resource_base'
|
3
|
+
require 'itamae-plugin-resource-portage/resources/portage_package'
|
4
|
+
require 'itamae-plugin-resource-portage/resources/portage_accept_keywords'
|
5
|
+
require 'itamae-plugin-resource-portage/resources/portage_mask'
|
6
|
+
require 'itamae-plugin-resource-portage/resources/portage_unmask'
|
7
|
+
require 'itamae-plugin-resource-portage/resources/portage_pin'
|
8
|
+
require 'itamae-plugin-resource-portage/resources/portage_use'
|
9
|
+
|
10
|
+
module ItamaePluginResourcePortage
|
11
|
+
module Resources
|
12
|
+
class Portage < Itamae::Resource::Base
|
13
|
+
include ResourceBase::Attributes
|
14
|
+
define_attribute :action, default: :install
|
15
|
+
|
16
|
+
define_attribute :emerge_cmd, type: String, default: '/usr/bin/emerge'
|
17
|
+
define_attribute :eix_cmd, type: String, default: '/usr/bin/eix'
|
18
|
+
# define_attribute :eix_update_cmd, type: String, default: '/usr/bin/eix-update'
|
19
|
+
|
20
|
+
define_attribute :package_use_file, type: String
|
21
|
+
define_attribute :package_mask_file, type: String
|
22
|
+
define_attribute :package_unmask_file, type: String
|
23
|
+
define_attribute :package_accept_keywords_file, type: String
|
24
|
+
|
25
|
+
define_attribute :unmask, type: [NilClass, TrueClass, FalseClass]
|
26
|
+
define_attribute :pin, type: [TrueClass, FalseClass], default: false
|
27
|
+
|
28
|
+
define_attribute :noreplace, type: [TrueClass, FalseClass], default: true
|
29
|
+
define_attribute :oneshot, type: [TrueClass, FalseClass], default: false
|
30
|
+
|
31
|
+
define_attribute :flags, type: [Array, String]
|
32
|
+
define_attribute :keywords, type: [Array, String]
|
33
|
+
|
34
|
+
def pre_action
|
35
|
+
if attributes.pin && attributes.unmask
|
36
|
+
raise ArgumentError, "pin and unmask can't be specified at once"
|
37
|
+
end
|
38
|
+
|
39
|
+
if attributes.pin && !attributes.version
|
40
|
+
raise ArgumentError, "Should specify version when you want to pin"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def action_install
|
45
|
+
recipes = []
|
46
|
+
recipes << recipe_use(:add) if attributes.flags
|
47
|
+
recipes << recipe_accept_keywords(:add) if accept_keywords?
|
48
|
+
case
|
49
|
+
when attributes.pin
|
50
|
+
recipes << recipe_pin(:pin)
|
51
|
+
when unmask?
|
52
|
+
recipes << recipe_unmask(:add)
|
53
|
+
end
|
54
|
+
recipes << recipe_package(:install)
|
55
|
+
Itamae::RecipeChildren.new(recipes).run
|
56
|
+
end
|
57
|
+
|
58
|
+
def action_remove
|
59
|
+
recipes = []
|
60
|
+
recipes << recipe_use(:remove) if attributes.flags
|
61
|
+
recipes << recipe_accept_keywords(:remove) if accept_keywords?
|
62
|
+
case
|
63
|
+
when attributes.pin
|
64
|
+
recipes << recipe_pin(:unpin)
|
65
|
+
when unmask?
|
66
|
+
recipes << recipe_unmask(:remove)
|
67
|
+
end
|
68
|
+
recipes << recipe_package(:remove)
|
69
|
+
Itamae::RecipeChildren.new(recipes).run
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def unmask?
|
75
|
+
if attributes.unmask.nil?
|
76
|
+
!!attributes.version
|
77
|
+
else
|
78
|
+
attributes.unmask
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def accept_keywords?
|
83
|
+
if attributes.keywords.nil?
|
84
|
+
!!attributes.version
|
85
|
+
else
|
86
|
+
!(attributes.keywords ||[] ).empty?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def recipe_use(_action)
|
91
|
+
_name, _version, _slot, _atom = self.attributes.name, self.attributes.version, self.attributes.slot, self.attributes.atom
|
92
|
+
_target = self.attributes.package_use_file
|
93
|
+
_flags = self.attributes.flags
|
94
|
+
PortageUse.new(recipe, _name) do
|
95
|
+
action _action
|
96
|
+
target _target
|
97
|
+
flags _flags
|
98
|
+
version _version
|
99
|
+
slot _slot
|
100
|
+
atom _atom
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def recipe_accept_keywords(_action)
|
105
|
+
_name, _version, _slot, _atom = self.attributes.name, self.attributes.version, self.attributes.slot, self.attributes.atom
|
106
|
+
_target = self.attributes.package_accept_keywords_file
|
107
|
+
_keywords = self.attributes.keywords
|
108
|
+
PortageAcceptKeywords.new(recipe, _name) do
|
109
|
+
action _action
|
110
|
+
target _target
|
111
|
+
keywords _keywords if _keywords
|
112
|
+
version _version
|
113
|
+
slot _slot
|
114
|
+
atom _atom
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def recipe_pin(_action)
|
119
|
+
_name, _version = self.attributes.name, self.attributes.version
|
120
|
+
PortagePin.new(recipe, _name) do
|
121
|
+
action _action
|
122
|
+
version _version
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def recipe_unmask(_action)
|
127
|
+
_name, _version, _slot, _atom = self.attributes.name, self.attributes.version, self.attributes.slot, self.attributes.atom
|
128
|
+
_target = self.attributes.package_unmask_file
|
129
|
+
PortageUnmask.new(recipe, _name) do
|
130
|
+
action _action
|
131
|
+
target _target
|
132
|
+
version _version
|
133
|
+
slot _slot
|
134
|
+
atom _atom
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def recipe_package(_action)
|
139
|
+
_name, _version, _slot, _atom = self.attributes.name, self.attributes.version, self.attributes.slot, self.attributes.atom
|
140
|
+
_emerge_cmd, _eix_cmd = self.attributes.emerge_cmd, self.attributes.eix_cmd
|
141
|
+
_noreplace, _oneshot = self.attributes.noreplace, self.attributes.oneshot
|
142
|
+
PortagePackage.new(recipe, _name) do
|
143
|
+
action _action
|
144
|
+
version _version if _version
|
145
|
+
slot _slot
|
146
|
+
atom _atom
|
147
|
+
|
148
|
+
emerge_cmd _emerge_cmd
|
149
|
+
eix_cmd _eix_cmd
|
150
|
+
|
151
|
+
noreplace _noreplace
|
152
|
+
oneshot _oneshot
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/portage_file_resource_base'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
module Resources
|
5
|
+
class PortageAcceptKeywords < PortageFileResourceBase
|
6
|
+
define_attribute :keywords, type: [String, Array, NilClass]
|
7
|
+
|
8
|
+
def value
|
9
|
+
attributes.keywords || default_accept_keywords
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_accept_keywords
|
13
|
+
@default_accept_keywords ||= begin
|
14
|
+
arch = backend.run_command(%w(eix --print ARCH)).stdout.chomp
|
15
|
+
["~#{arch}"]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def target_default_directory
|
20
|
+
"/etc/portage/package.accept_keywords"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/portage_file_resource_base'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
module Resources
|
5
|
+
class PortageMask < PortageFileResourceBase
|
6
|
+
def value
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def target_default_directory
|
11
|
+
"/etc/portage/package.mask"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/resource_base'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
module Resources
|
5
|
+
class PortagePackage < ResourceBase
|
6
|
+
define_attribute :action, default: :install
|
7
|
+
define_attribute :emerge_cmd, type: String, default: '/usr/bin/emerge'
|
8
|
+
define_attribute :eix_cmd, type: String, default: '/usr/bin/eix'
|
9
|
+
# define_attribute :eix_update_cmd, type: String, default: '/usr/bin/eix-update'
|
10
|
+
|
11
|
+
define_attribute :noreplace, type: [TrueClass, FalseClass], default: true
|
12
|
+
define_attribute :oneshot, type: [TrueClass, FalseClass], default: false
|
13
|
+
|
14
|
+
def pre_action
|
15
|
+
atom
|
16
|
+
case @current_action
|
17
|
+
when :unmerge, :remove
|
18
|
+
attributes.installed = false
|
19
|
+
when :update, :install
|
20
|
+
attributes.installed = true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_current_attributes
|
25
|
+
check_installation
|
26
|
+
end
|
27
|
+
|
28
|
+
def action_install
|
29
|
+
case
|
30
|
+
when !attributes.noreplace
|
31
|
+
emerge!
|
32
|
+
when !current.installed && attributes.installed
|
33
|
+
emerge!
|
34
|
+
when current.installed && (attributes.version.nil? || (attributes.version != current.version))
|
35
|
+
emerge!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
alias action_update action_install
|
39
|
+
|
40
|
+
def action_unmerge
|
41
|
+
case
|
42
|
+
when current.installed
|
43
|
+
unmerge!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias action_remove action_unmerge
|
47
|
+
|
48
|
+
def unmerge!
|
49
|
+
run_command([attributes.emerge_cmd, '--nospinner', '--color=n', '--rage-clean', '-v', atom])
|
50
|
+
updated!
|
51
|
+
end
|
52
|
+
|
53
|
+
def emerge!
|
54
|
+
update = @current_action == :update ? %w(-u) : []
|
55
|
+
noreplace = attributes.noreplace ? %w(--noreplace) : []
|
56
|
+
run_command([attributes.emerge_cmd, '--nospinner', '--color=n', '-v', *update, *noreplace, atom])
|
57
|
+
updated!
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def eix_determinable?
|
63
|
+
!attributes.atom && (!attributes.version || atom_op == '=')
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_installation
|
67
|
+
if eix_determinable?
|
68
|
+
result = eix(attributes.name).find {|_| _[:name] == attributes.name }
|
69
|
+
if !result
|
70
|
+
raise ArgumentError, "package #{attributes.name} not found on eix"
|
71
|
+
end
|
72
|
+
|
73
|
+
installed_version = if attributes.slot
|
74
|
+
result[:installed_versions][attributes.slot]
|
75
|
+
else
|
76
|
+
result[:installed_version]
|
77
|
+
end
|
78
|
+
if installed_version
|
79
|
+
current.installed = true
|
80
|
+
current.version = result[:installed_version]
|
81
|
+
else
|
82
|
+
current.installed = false
|
83
|
+
current.version = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
if !attributes.version
|
87
|
+
attributes.version = if attributes.slot
|
88
|
+
result[:best_slot_versions][attributes.slot]
|
89
|
+
else
|
90
|
+
result[:best_version]
|
91
|
+
end
|
92
|
+
@atom = nil; atom
|
93
|
+
end
|
94
|
+
else
|
95
|
+
update = @current_action == :update ? %w(-u) : []
|
96
|
+
noreplace = attributes.noreplace ? %w(--noreplace) : []
|
97
|
+
pvn = run_command([attributes.emerge_cmd, '--nospinner', '--color=n', '-pv', *noreplace, *update, atom])
|
98
|
+
|
99
|
+
current.installed = /Total: 0 packages/ === pvn.stdout
|
100
|
+
if current.installed
|
101
|
+
current.version = attributes.version
|
102
|
+
else
|
103
|
+
current.version = nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def eix(*options)
|
109
|
+
result = run_command(['env', "MYVERSION=<version>:<slot>{!last} {}", attributes.eix_cmd, '--nocolor', '--pure-packages', '--format', "<category>/<name>|<installedversions:MYVERSION>|<bestslotversions:MYVERSION>|<bestversion:MYVERSION>\\n", *options], error: false)
|
110
|
+
|
111
|
+
unless result.exit_status.zero?
|
112
|
+
return []
|
113
|
+
end
|
114
|
+
|
115
|
+
result.stdout.each_line.map do |line|
|
116
|
+
name, installedversions, bestslotversions, bestversion = line.chomp.split(?|, 4)
|
117
|
+
|
118
|
+
best_version, best_version_slot = bestversion.split(?:,2)
|
119
|
+
|
120
|
+
installedversion = installedversions.split(/ /).last
|
121
|
+
if installedversion
|
122
|
+
installed_version, installed_version_slot = installedversion.split(?:,2)
|
123
|
+
end
|
124
|
+
|
125
|
+
{
|
126
|
+
name: name,
|
127
|
+
installed_versions: Hash[installedversions.split(/ /).map{ |_| _.split(?:, 2) }.group_by(&:last).map { |k,v| [k, v.map(&:first).last] }],
|
128
|
+
best_slot_versions: Hash[bestslotversions.split(/ /).map{ |_| _.split(?:, 2) }.group_by(&:last).map { |k,v| [k, v.map(&:first).last] }],
|
129
|
+
best_version: best_version,
|
130
|
+
best_version_slot: best_version_slot,
|
131
|
+
installed_version: installed_version,
|
132
|
+
installed_version_slot: installed_version_slot,
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'itamae'
|
2
|
+
require 'itamae-plugin-resource-portage/resources/portage_mask'
|
3
|
+
require 'itamae-plugin-resource-portage/resources/portage_unmask'
|
4
|
+
|
5
|
+
module ItamaePluginResourcePortage
|
6
|
+
module Resources
|
7
|
+
class PortagePin < Itamae::Resource::Base
|
8
|
+
define_attribute :name, type: String, default_name: true
|
9
|
+
define_attribute :action, default: :pin
|
10
|
+
define_attribute :version, type: String, required: true
|
11
|
+
|
12
|
+
def action_pin
|
13
|
+
Itamae::RecipeChildren.new([mask(:add), unmask(:add)]).run
|
14
|
+
end
|
15
|
+
|
16
|
+
def action_unpin
|
17
|
+
Itamae::RecipeChildren.new([mask(:remove), unmask(:remove)]).run
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def mask(_action)
|
23
|
+
PortageMask.new(recipe, self.attributes.name) do
|
24
|
+
action _action
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def unmask(_action)
|
29
|
+
_version = self.attributes.version
|
30
|
+
PortageUnmask.new(recipe, self.attributes.name) do
|
31
|
+
action _action
|
32
|
+
version "=#{_version}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/portage_file_resource_base'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
module Resources
|
5
|
+
class PortageUnmask < PortageFileResourceBase
|
6
|
+
def value
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def target_default_directory
|
11
|
+
"/etc/portage/package.unmask"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'itamae-plugin-resource-portage/portage_file_resource_base'
|
2
|
+
|
3
|
+
module ItamaePluginResourcePortage
|
4
|
+
module Resources
|
5
|
+
class PortageUse < PortageFileResourceBase
|
6
|
+
define_attribute :flags, type: Array
|
7
|
+
|
8
|
+
def value
|
9
|
+
attributes.flags
|
10
|
+
end
|
11
|
+
|
12
|
+
def target_default_directory
|
13
|
+
"/etc/portage/package.use"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "itamae/plugin/resource/portage"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/script/setup
ADDED
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: itamae-plugin-resource-portage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sorah (Shota Fukumori)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: itamae
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- her@sorah.jp
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- itamae-plugin-resource-portage.gemspec
|
84
|
+
- lib/itamae-plugin-resource-portage.rb
|
85
|
+
- lib/itamae-plugin-resource-portage/portage_file_resource_base.rb
|
86
|
+
- lib/itamae-plugin-resource-portage/resource_base.rb
|
87
|
+
- lib/itamae-plugin-resource-portage/resources.rb
|
88
|
+
- lib/itamae-plugin-resource-portage/resources/portage.rb
|
89
|
+
- lib/itamae-plugin-resource-portage/resources/portage_accept_keywords.rb
|
90
|
+
- lib/itamae-plugin-resource-portage/resources/portage_mask.rb
|
91
|
+
- lib/itamae-plugin-resource-portage/resources/portage_package.rb
|
92
|
+
- lib/itamae-plugin-resource-portage/resources/portage_pin.rb
|
93
|
+
- lib/itamae-plugin-resource-portage/resources/portage_unmask.rb
|
94
|
+
- lib/itamae-plugin-resource-portage/resources/portage_use.rb
|
95
|
+
- lib/itamae-plugin-resource-portage/version.rb
|
96
|
+
- lib/itamae/plugin/resource/portage.rb
|
97
|
+
- script/console
|
98
|
+
- script/setup
|
99
|
+
homepage: https://github.com/sorah/itamae-plugin-resource-portage
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
metadata: {}
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.3.1
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.5.1
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: Itamae resources for Gentoo Portage
|
123
|
+
test_files: []
|