reaper-man 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/CONTRIBUTING.md +25 -0
- data/LICENSE +13 -0
- data/README.md +55 -0
- data/bin/reaper-man +83 -0
- data/lib/reaper-man/command/package/add.rb +24 -0
- data/lib/reaper-man/command/package/remove.rb +24 -0
- data/lib/reaper-man/command/package.rb +12 -0
- data/lib/reaper-man/command/repository/generate.rb +28 -0
- data/lib/reaper-man/command/repository.rb +11 -0
- data/lib/reaper-man/command/sign.rb +21 -0
- data/lib/reaper-man/command.rb +11 -0
- data/lib/reaper-man/error.rb +20 -0
- data/lib/reaper-man/generator/apt.rb +117 -0
- data/lib/reaper-man/generator/rubygems.rb +91 -0
- data/lib/reaper-man/generator/yum.rb +10 -0
- data/lib/reaper-man/generator.rb +98 -0
- data/lib/reaper-man/package_list/deb.rb +150 -0
- data/lib/reaper-man/package_list/gem.rb +80 -0
- data/lib/reaper-man/package_list/rpm.rb +11 -0
- data/lib/reaper-man/package_list.rb +127 -0
- data/lib/reaper-man/signer/deb.rb +47 -0
- data/lib/reaper-man/signer/rubygems.rb +17 -0
- data/lib/reaper-man/signer.rb +62 -0
- data/lib/reaper-man/util-scripts/auto-debsigs +30 -0
- data/lib/reaper-man/utils/process.rb +114 -0
- data/lib/reaper-man/utils.rb +27 -0
- data/lib/reaper-man.rb +13 -0
- data/reaper-man.gemspec +17 -0
- metadata +78 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e552f3927ecc938f4e80fe58a77e2ed46e3330b
|
4
|
+
data.tar.gz: 58680f7d1b1be0d7043340f423a086450ff6bfc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c977b039699149eba6dcbcf70be527426de5d986c9a0acc8f3cedd878c0e108d6f41e94e883b039c648c8178f13bd7e44c219c0f004f09bc2335cf6569b5875
|
7
|
+
data.tar.gz: 91b0add2951920e67f1364f8e2900e0875fed65f5b3c6b7a568fe249f497ae47469277c85ea0824486b7239ae81c60368ca6082406777088e210f1113c0ede39
|
data/CHANGELOG.md
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
## Branches
|
4
|
+
|
5
|
+
### `master` branch
|
6
|
+
|
7
|
+
The master branch is the current stable released version.
|
8
|
+
|
9
|
+
### `develop` branch
|
10
|
+
|
11
|
+
The develop branch is the current edge of development.
|
12
|
+
|
13
|
+
## Pull requests
|
14
|
+
|
15
|
+
* https://github.com/hw-labs/reaper-man
|
16
|
+
|
17
|
+
Please base all pull requests of the `develop` branch. Merges to
|
18
|
+
`master` only occur through the `develop` branch. Pull requests
|
19
|
+
based on `master` will likely be cherry picked.
|
20
|
+
|
21
|
+
## Issues
|
22
|
+
|
23
|
+
Need to report an issue? Use the github issues:
|
24
|
+
|
25
|
+
* https://github.com/hw-labs/reaper-man/issues
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2015 Chris Roberts
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
## Reaper Man
|
2
|
+
#### "What can the harvest hope for, if not for the care of the Reaper Man?"
|
3
|
+
##### - Terry Pratchett
|
4
|
+
|
5
|
+
Grow code, harvest packages
|
6
|
+
|
7
|
+
### Harvests
|
8
|
+
|
9
|
+
Package repository is maintained via `JSON` file. Packages are added or removed
|
10
|
+
from the `JSON` registry. Repository generation will result in skeleton repository
|
11
|
+
with the proper `Release` and `Packages` files. Package paths will be not exist
|
12
|
+
within the generated repository. Resolving that issue is left to the reader.
|
13
|
+
|
14
|
+
### Support
|
15
|
+
|
16
|
+
#### Enabled
|
17
|
+
|
18
|
+
* deb/apt
|
19
|
+
* gem/rubygems
|
20
|
+
|
21
|
+
#### In Progress
|
22
|
+
|
23
|
+
* rpm/yum
|
24
|
+
|
25
|
+
### Usage
|
26
|
+
|
27
|
+
#### Add package to registry
|
28
|
+
|
29
|
+
```
|
30
|
+
> reaper-man package add my_pkg.deb --packages-file registry.json
|
31
|
+
```
|
32
|
+
|
33
|
+
### Remove package from registry
|
34
|
+
|
35
|
+
```
|
36
|
+
> reaper-man package remove my_pkg --packages-file registry.json
|
37
|
+
```
|
38
|
+
|
39
|
+
or remove a specific version
|
40
|
+
|
41
|
+
```
|
42
|
+
> reaper-man package remove my_pkg 1.0.0 --packages-file registry.json
|
43
|
+
```
|
44
|
+
|
45
|
+
### Create a repository
|
46
|
+
|
47
|
+
```
|
48
|
+
> reaper-man repo create --packages-file registry.json --package-system apt --output-directory /tmp/test-repo
|
49
|
+
```
|
50
|
+
|
51
|
+
This can also be used to update an existing repository structure.
|
52
|
+
|
53
|
+
## Infos
|
54
|
+
* Repository: https://github.com/hw-labs/reaper-man
|
55
|
+
* IRC: Freenode @ #heavywater
|
data/bin/reaper-man
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bogo-cli'
|
4
|
+
require 'reaper-man'
|
5
|
+
|
6
|
+
Bogo::Cli::Setup.define do
|
7
|
+
|
8
|
+
on :v, :version, 'Print version' do
|
9
|
+
puts "reaper-man - Repository generation tool - [Version: #{ReaperMan::VERSION}]"
|
10
|
+
exit
|
11
|
+
end
|
12
|
+
|
13
|
+
common_options = lambda do
|
14
|
+
on :c, :config=, 'Path to configuration file'
|
15
|
+
on :k, :'signing-key=', 'Path to key for signing generated files'
|
16
|
+
on :t, :'signing-type=', 'Signing type name'
|
17
|
+
on :s, :sign, 'Enable file signing'
|
18
|
+
on :S, :'package-system=', 'Packaging system to generate repository (apt/yum/rubygems/supermarket)'
|
19
|
+
on :p, :'packages-file=', 'Path to packages file', :required => true
|
20
|
+
end
|
21
|
+
|
22
|
+
command :repo do
|
23
|
+
description 'Package repository generation'
|
24
|
+
|
25
|
+
repo_options = lambda do
|
26
|
+
on :o, :output_directory=, 'Path to output repository structure', :required => true
|
27
|
+
end
|
28
|
+
|
29
|
+
command :generate do
|
30
|
+
instance_exec(&common_options)
|
31
|
+
instance_exec(&repo_options)
|
32
|
+
description 'Generate repository'
|
33
|
+
|
34
|
+
run do |opts, args|
|
35
|
+
ReaperMan::Command::Repository::Generate.new(opts, args).execute!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
command :package do
|
42
|
+
description 'Update packages within repositories'
|
43
|
+
|
44
|
+
package_options = lambda do
|
45
|
+
on :O, :origin=, 'Name of repository origin', :default => 'Default'
|
46
|
+
on :N, :codename=, 'Code name to add package', :default => 'all'
|
47
|
+
on :C, :component=, 'Component name to add package', :default => 'main'
|
48
|
+
end
|
49
|
+
|
50
|
+
command :add do
|
51
|
+
description 'Add package to repository manifest'
|
52
|
+
instance_exec(&common_options)
|
53
|
+
instance_exec(&package_options)
|
54
|
+
|
55
|
+
run do |opts, args|
|
56
|
+
ReaperMan::Command::Package::Add.new(opts, args).execute!
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
command :remove do
|
61
|
+
description 'Remove package from repository manifest'
|
62
|
+
instance_exec(&common_options)
|
63
|
+
instance_exec(&package_options)
|
64
|
+
|
65
|
+
run do |opts, args|
|
66
|
+
ReaperMan::Command::Package::Remove.new(opts, args).execute!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
command :sign do
|
73
|
+
description 'Sign package(s)'
|
74
|
+
|
75
|
+
on :S, :'package-system=', 'Packaging system to generate repository (apt/yum/rubygems/supermarket)', :required => true
|
76
|
+
on :Z, :'signing-chunk-size=', 'Number of packages to sign at once', :default => 20, :as => Integer
|
77
|
+
|
78
|
+
run do |opts, args|
|
79
|
+
ReaperMan::Command::Sign.new(opts, args).execute!
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
class Command
|
5
|
+
class Package
|
6
|
+
|
7
|
+
class Add < Package
|
8
|
+
|
9
|
+
def execute!
|
10
|
+
arguments.each do |path|
|
11
|
+
run_action "Adding package to repository manifest: #{path}" do
|
12
|
+
list = ReaperMan::PackageList.new(config[:packages_file], config)
|
13
|
+
list.add_package(path)
|
14
|
+
list.write!
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
class Command
|
5
|
+
class Package
|
6
|
+
|
7
|
+
class Remove < Package
|
8
|
+
|
9
|
+
def execute!
|
10
|
+
arguments.each do |pkg|
|
11
|
+
run_action "Remove package from repository manifest: #{pkg}" do
|
12
|
+
list = ReaperMan::PackageList.new(config[:packages_file], config)
|
13
|
+
list.remove_package(pkg)
|
14
|
+
list.write!
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
class Command
|
5
|
+
class Repository
|
6
|
+
|
7
|
+
class Generate < Repository
|
8
|
+
|
9
|
+
def execute!
|
10
|
+
run_action 'Generating repository' do
|
11
|
+
ReaperMan::Generator.new(
|
12
|
+
config.merge(
|
13
|
+
Smash.new(
|
14
|
+
:package_config => MultiJson.load(
|
15
|
+
File.read(config[:packages_file])
|
16
|
+
).to_smash
|
17
|
+
)
|
18
|
+
)
|
19
|
+
).generate!
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
class Command
|
5
|
+
class Sign < Command
|
6
|
+
|
7
|
+
def execute!
|
8
|
+
run_action 'Signing file(s)' do
|
9
|
+
signer = Signer.new(config)
|
10
|
+
files = Dir.glob(File.join(arguments.first, '**', '*'))
|
11
|
+
files.delete_if do |path|
|
12
|
+
!File.file?(path)
|
13
|
+
end
|
14
|
+
signer.package(*files)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
# Standard error for reaper errors
|
5
|
+
class Error < StandardError
|
6
|
+
# exit code for exception
|
7
|
+
CODE = -1
|
8
|
+
|
9
|
+
# @return [Integer]
|
10
|
+
def exit_code
|
11
|
+
self.class.const_get(:CODE)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Define errors here
|
15
|
+
['UnknownCommand', 'FileNotFound'].each_with_index do |klass_name, idx|
|
16
|
+
self.class_eval("class #{klass_name} < Error; CODE=#{idx + 1}; end;")
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
class Generator
|
5
|
+
# Generator methods for apt
|
6
|
+
module Apt
|
7
|
+
|
8
|
+
# Generate the repository
|
9
|
+
def generate!
|
10
|
+
generate_dists(package_config[:apt])
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generate the repository dists
|
14
|
+
#
|
15
|
+
# @param pkg_hash [Hash] repository description
|
16
|
+
# @return [TrueClass]
|
17
|
+
def generate_dists(pkg_hash)
|
18
|
+
pkg_hash.each do |origin_name, dists|
|
19
|
+
dists.each do |dist_name, dist_args|
|
20
|
+
dist_args[:components].each do |component_name, arches|
|
21
|
+
arches.each do |arch_name, packages|
|
22
|
+
package_file(origin_name, dist_name, component_name, arch_name, packages)
|
23
|
+
release_headers = Smash.new
|
24
|
+
release_headers['Label'] = dist_args['label']
|
25
|
+
release_headers['Archive'] = dist_name
|
26
|
+
sign_file_if_setup do
|
27
|
+
release_file(origin_name, dist_name, component_name, arch_name, release_headers)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
release_headers = Smash[
|
32
|
+
%w(Codename Suite Label Description Version).map do |field_name|
|
33
|
+
if(val = dist_args[field_name.downcase])
|
34
|
+
[field_name, val]
|
35
|
+
end
|
36
|
+
end.compact
|
37
|
+
]
|
38
|
+
release_headers['Components'] = dist_args[:components].keys.join(' ')
|
39
|
+
sign_file_if_setup do
|
40
|
+
release_file(origin_name, dist_name, release_headers)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sign file if configured for signing
|
48
|
+
#
|
49
|
+
# @yield block returning file path
|
50
|
+
# @return [String] file path
|
51
|
+
def sign_file_if_setup
|
52
|
+
path = yield
|
53
|
+
if(signer && options[:sign])
|
54
|
+
signer.file(path)
|
55
|
+
end
|
56
|
+
path
|
57
|
+
end
|
58
|
+
|
59
|
+
# Create Packages file
|
60
|
+
#
|
61
|
+
# @param args [String] argument list for file path
|
62
|
+
# @return [String] path to compressed Packages file
|
63
|
+
def package_file(*args)
|
64
|
+
pkgs = args.pop
|
65
|
+
args.insert(1, 'dists')
|
66
|
+
create_file(*args.push('Packages')) do |file|
|
67
|
+
pkgs.each do |pkg_name, pkgs|
|
68
|
+
pkgs.each do |pkg_version, pkg_meta|
|
69
|
+
pkg_meta.each do |field_name, field_value|
|
70
|
+
if(field_value)
|
71
|
+
file.puts "#{field_name}: #{field_value}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
file.puts
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
compress_file(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Create Release file
|
82
|
+
#
|
83
|
+
# @param args [String] argument list for file path
|
84
|
+
# @return [TrueClass]
|
85
|
+
def release_file(*args)
|
86
|
+
header = args.detect{|a| a.is_a?(Hash)}
|
87
|
+
header ? args.delete(header) : header = Smash.new
|
88
|
+
header.merge(Smash[%w(Origin Codename Component Architecture).zip(args)])
|
89
|
+
header['Date'] = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S %Z')
|
90
|
+
args.insert(1, 'dists')
|
91
|
+
create_file(*args.dup.push('Release')) do |file|
|
92
|
+
contents = Dir.glob(File.join(File.dirname(file.path), '**', '*'))
|
93
|
+
header_content = header.map do |key, value|
|
94
|
+
next unless value
|
95
|
+
"#{key.to_s.capitalize}: #{value}"
|
96
|
+
end.compact.join("\n")
|
97
|
+
file.puts header_content
|
98
|
+
[['MD5Sum', :md5], ['SHA1', :sha1], ['SHA256', :sha256]].each do |field, digest|
|
99
|
+
file.puts "#{field}:"
|
100
|
+
contents.each do |content|
|
101
|
+
next if File.expand_path(content) == File.expand_path(file.path) || File.directory?(content)
|
102
|
+
File.open(content, 'r') do |content_file|
|
103
|
+
line = [' ']
|
104
|
+
line << checksum(content_file, digest)
|
105
|
+
line << content_file.size
|
106
|
+
line << content_file.path.sub(File.dirname(file.path), '').sub(/^\//, '')
|
107
|
+
file.puts line.join(' ')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'reaper-man'
|
2
|
+
|
3
|
+
module ReaperMan
|
4
|
+
class Generator
|
5
|
+
# Generator methods for rubygems
|
6
|
+
module Rubygems
|
7
|
+
|
8
|
+
# Generate the rubygems repository
|
9
|
+
#
|
10
|
+
def generate!
|
11
|
+
generate_gemstore(package_config[:rubygem])
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_gemstore(gems)
|
15
|
+
generate_indexing(gems)
|
16
|
+
write_quick_specs(gems.fetch(:release, {}))
|
17
|
+
write_quick_specs(gems.fetch(:prerelease, {}))
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate_indexing(gems)
|
21
|
+
build_spec_file('specs', gems.fetch(:release, {}))
|
22
|
+
build_spec_file('latest_specs', gems.fetch(:release, {}))
|
23
|
+
build_spec_file('prerelease', gems.fetch(:prerelease, {}))
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_index(gems)
|
27
|
+
[].tap do |list|
|
28
|
+
gems.each do |name, all|
|
29
|
+
all.each do |version, info|
|
30
|
+
list << [name, Gem::Version.new(version.dup), info[:platform]]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def marshal_path
|
37
|
+
['Marshal', marshal_version].join('.')
|
38
|
+
end
|
39
|
+
|
40
|
+
def marshal_version
|
41
|
+
[Marshal::MAJOR_VERSION, Marshal::MINOR_VERSION].join('.')
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_spec_file(name, gems)
|
45
|
+
index = create_index(gems)
|
46
|
+
create_file("#{name}.#{marshal_version}") do |file|
|
47
|
+
file.write(Marshal.dump(index))
|
48
|
+
end
|
49
|
+
compress_file("#{name}.#{marshal_version}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def write_quick_specs(gems)
|
53
|
+
gems.each do |name, list|
|
54
|
+
list.each do |version, info|
|
55
|
+
spec = Gem::Specification.new(name)
|
56
|
+
info.each do |var, value|
|
57
|
+
if(spec.respond_to?("#{var}="))
|
58
|
+
begin
|
59
|
+
spec.send("#{var}=", value)
|
60
|
+
rescue Gem::InvalidSpecificationException => e
|
61
|
+
# TODO: Do we have a logger in this project?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
spec.version = Gem::Version.new(info[:version])
|
66
|
+
spec.date = Time.parse(info[:date])
|
67
|
+
info[:dependencies].each do |dep|
|
68
|
+
spec.add_dependency(*dep)
|
69
|
+
end
|
70
|
+
create_file('quick', marshal_path, "#{name}-#{version}.gemspec.rz") do |file|
|
71
|
+
file.write(Marshal.dump(spec))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Sign file if configured for signing
|
78
|
+
#
|
79
|
+
# @yield block returning file path
|
80
|
+
# @return [String] file path
|
81
|
+
def sign_file_if_setup
|
82
|
+
path = yield
|
83
|
+
if(signer && options[:sign])
|
84
|
+
signer.file(path)
|
85
|
+
end
|
86
|
+
path
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'zlib'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'reaper-man'
|
6
|
+
|
7
|
+
module ReaperMan
|
8
|
+
# Repository generator
|
9
|
+
class Generator
|
10
|
+
|
11
|
+
autoload :Apt, 'reaper-man/generator/apt'
|
12
|
+
autoload :Rpm, 'reaper-man/generator/rpm'
|
13
|
+
autoload :Rubygems, 'reaper-man/generator/rubygems'
|
14
|
+
|
15
|
+
include Utils::Checksum
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
attr_reader :package_system
|
19
|
+
# @return [Hash]
|
20
|
+
attr_reader :package_config
|
21
|
+
# @return [Signer, NilClass]
|
22
|
+
attr_reader :signer
|
23
|
+
# @return [Hash]
|
24
|
+
attr_reader :options
|
25
|
+
|
26
|
+
# Create new instance
|
27
|
+
#
|
28
|
+
# @param args [Hash]
|
29
|
+
# @option args [String] :package_system apt/gem/etc...
|
30
|
+
# @option args [Hash] :package_config
|
31
|
+
# @option args [Signer] :signer
|
32
|
+
def initialize(args={})
|
33
|
+
@package_system = args[:package_system]
|
34
|
+
@package_config = args.fetch(:package_config, Smash.new)
|
35
|
+
@signer = args[:signer]
|
36
|
+
@options = args
|
37
|
+
extend self.class.const_get(package_system.to_s.split('_').map(&:capitalize).join.to_sym)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Generate new repository
|
41
|
+
def generate!
|
42
|
+
raise NoMethodError.new 'Not implemented'
|
43
|
+
end
|
44
|
+
|
45
|
+
# Create new file
|
46
|
+
#
|
47
|
+
# @param name [String] argument list joined to output directory
|
48
|
+
# @yield block executed with file
|
49
|
+
# @yieldparam [String] path to file
|
50
|
+
# @return [String] path to file
|
51
|
+
def create_file(*name)
|
52
|
+
path = File.join(options[:output_directory], *name)
|
53
|
+
FileUtils.mkdir_p(File.dirname(path))
|
54
|
+
file = File.open(path, 'wb+')
|
55
|
+
if(block_given?)
|
56
|
+
yield file
|
57
|
+
end
|
58
|
+
file.close unless file.closed?
|
59
|
+
path
|
60
|
+
end
|
61
|
+
|
62
|
+
# Updates a file
|
63
|
+
#
|
64
|
+
# @param name [String] argument list joined to output directory
|
65
|
+
# @yield block executed with file
|
66
|
+
# @yieldparam [String] path to file
|
67
|
+
# @return [String] path to file
|
68
|
+
def for_file(*name)
|
69
|
+
path = File.join(options[:output_directory], *name)
|
70
|
+
FileUtils.mkdir_p(File.dirname(path))
|
71
|
+
if(block_given?)
|
72
|
+
file = File.open(path, 'a+')
|
73
|
+
yield file
|
74
|
+
file.close
|
75
|
+
end
|
76
|
+
path
|
77
|
+
end
|
78
|
+
|
79
|
+
# Compress a file (gzip)
|
80
|
+
#
|
81
|
+
# @param name [String] argument list joined to output directory
|
82
|
+
# @return [String] path to compressed file
|
83
|
+
def compress_file(*path)
|
84
|
+
compressed_path = path.dup
|
85
|
+
compressed_path.push("#{compressed_path.pop}.gz")
|
86
|
+
base_file = File.open(for_file(path))
|
87
|
+
create_file(compressed_path) do |file|
|
88
|
+
compressor = Zlib::GzipWriter.new(file)
|
89
|
+
while(data = base_file.read(2048))
|
90
|
+
compressor.write(data)
|
91
|
+
end
|
92
|
+
compressor.close
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|