reaper-man 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|