s3repo 1.0.0 → 2.0.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/.circle-ruby +3 -0
- data/.prospectus +21 -7
- data/.rubocop.yml +5 -2
- data/Gemfile +0 -1
- data/README.md +1 -1
- data/Rakefile +1 -2
- data/bin/s3repo +31 -8
- data/circle.yml +7 -4
- data/lib/s3repo.rb +2 -0
- data/lib/s3repo/base.rb +4 -8
- data/lib/s3repo/cache.rb +13 -10
- data/lib/s3repo/client.rb +21 -8
- data/lib/s3repo/metadata.rb +12 -24
- data/lib/s3repo/repo.rb +17 -15
- data/lib/s3repo/signer.rb +17 -0
- data/lib/s3repo/templates.rb +52 -0
- data/lib/s3repo/version.rb +2 -1
- data/s3repo.gemspec +12 -9
- data/spec/spec_helper.rb +3 -0
- metadata +48 -27
- data/spec/fixtures/cassettes/cache.yml +0 -547
- data/spec/fixtures/cassettes/etag_cache.yml +0 -590
- data/spec/fixtures/cassettes/nil_cache.yml +0 -46
- data/spec/s3repo/base_spec.rb +0 -71
- data/spec/s3repo/cache_spec.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77fb43c11e189c5bfc7c347fa6b0d2efe566f9ff
|
4
|
+
data.tar.gz: 2ce120f3afd0e0b63a6d2f63c84822c3b974bc95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0c201ab4c0e8eefc8e7d2ba2490d92fdc9eb6e989c2b1a5cec9436580ca8c0ef5bf874052fac4056725343a9ccfbe5f96747cf1931297d81df5cee6ee251cf5
|
7
|
+
data.tar.gz: b2acfdd8d6386b69bddbd772d836b40d825a58b8adcbdf6a0ee64c484e397c94cbaf5d2e8cb99f303030bb031f24ed2e31e2bceab89fa801b587cea1fbfa0da7
|
data/.circle-ruby
ADDED
data/.prospectus
CHANGED
@@ -1,11 +1,25 @@
|
|
1
|
+
Prospectus.extra_dep('file', 'prospectus_circleci')
|
2
|
+
|
3
|
+
my_slug = 'amylum/s3repo'
|
4
|
+
|
1
5
|
item do
|
2
|
-
|
3
|
-
static
|
4
|
-
set 'green'
|
5
|
-
end
|
6
|
+
noop
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
deps do
|
9
|
+
item do
|
10
|
+
name 'gems'
|
11
|
+
|
12
|
+
expected do
|
13
|
+
static
|
14
|
+
set 'green'
|
15
|
+
end
|
16
|
+
|
17
|
+
actual do
|
18
|
+
gemnasium
|
19
|
+
slug my_slug
|
20
|
+
end
|
21
|
+
end
|
10
22
|
end
|
23
|
+
|
24
|
+
extend ProspectusCircleci::Build.new(my_slug)
|
11
25
|
end
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@ s3repo
|
|
3
3
|
|
4
4
|
[](https://rubygems.org/gems/s3repo)
|
5
5
|
[](https://gemnasium.com/amylum/s3repo)
|
6
|
-
[](https://circleci.com/gh/amylum/s3repo)
|
6
|
+
[](https://circleci.com/gh/amylum/s3repo)
|
7
7
|
[](https://codecov.io/github/amylum/s3repo)
|
8
8
|
[](https://www.codacy.com/app/akerl/s3repo)
|
9
9
|
[](https://tldrlegal.com/license/mit-license)
|
data/Rakefile
CHANGED
@@ -7,8 +7,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
8
8
|
desc 'Run Rubocop on the gem'
|
9
9
|
RuboCop::RakeTask.new(:rubocop) do |task|
|
10
|
-
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'bin/*']
|
11
10
|
task.fail_on_error = true
|
12
11
|
end
|
13
12
|
|
14
|
-
task default: [
|
13
|
+
task default: %i[spec rubocop build install]
|
data/bin/s3repo
CHANGED
@@ -2,49 +2,72 @@
|
|
2
2
|
|
3
3
|
require 's3repo'
|
4
4
|
require 'mercenary'
|
5
|
+
require 'yaml'
|
6
|
+
require 'cymbal'
|
5
7
|
|
6
8
|
def find(pattern, limits)
|
7
9
|
Dir.glob(pattern).select { |x| !limits || limits.include?(File.dirname(x)) }
|
8
10
|
end
|
9
11
|
|
12
|
+
def common_opts(cmd)
|
13
|
+
cmd.option :config_file, '-c', '--config FILE', 'Path of config file'
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_config(file)
|
17
|
+
file ||= 'config.yml'
|
18
|
+
file = File.expand_path(file)
|
19
|
+
raise("Config file not found: #{file}") unless File.exist? file
|
20
|
+
Cymbal.symbolize YAML.safe_load(File.read(file))
|
21
|
+
end
|
22
|
+
|
23
|
+
def repo(options)
|
24
|
+
config = load_config(options[:config_file])
|
25
|
+
S3Repo.new(config)
|
26
|
+
end
|
27
|
+
|
28
|
+
# rubocop:disable Metrics/BlockLength
|
10
29
|
Mercenary.program(:s3repo) do |p|
|
11
30
|
p.version S3Repo::VERSION
|
12
31
|
p.description 'Package management tool for Archlinux repos'
|
13
32
|
p.syntax 's3repo <subcommand> [args]'
|
14
33
|
|
15
34
|
p.command(:build) do |c|
|
35
|
+
common_opts(c)
|
16
36
|
c.syntax 'build [package...]'
|
17
37
|
c.description 'Build package files from PKGBUILDs'
|
18
38
|
|
19
|
-
c.action do |args,
|
20
|
-
|
39
|
+
c.action do |args, opts|
|
40
|
+
repo(opts).build_packages find('*/PKGBUILD', args)
|
21
41
|
end
|
22
42
|
end
|
23
43
|
|
24
44
|
p.command(:upload) do |c|
|
45
|
+
common_opts(c)
|
25
46
|
c.syntax 'upload [package...]'
|
26
47
|
c.description 'Upload packages to repo'
|
27
48
|
|
28
|
-
c.action do |args,
|
29
|
-
|
49
|
+
c.action do |args, opts|
|
50
|
+
repo(opts).add_packages find('*/*.pkg.tar.xz', args)
|
30
51
|
end
|
31
52
|
end
|
32
53
|
|
33
54
|
p.command(:remove) do |c|
|
55
|
+
common_opts(c)
|
34
56
|
c.syntax 'remove [package...]'
|
35
57
|
c.description 'Remove packages from repo DB'
|
36
58
|
|
37
|
-
c.action do |args,
|
38
|
-
|
59
|
+
c.action do |args, opts|
|
60
|
+
repo(opts).remove_packages args
|
39
61
|
end
|
40
62
|
end
|
41
63
|
|
42
64
|
p.command(:prune) do |c|
|
65
|
+
common_opts(c)
|
43
66
|
c.syntax 'prune'
|
44
67
|
c.description 'Prune orphaned files from the repo'
|
45
68
|
|
46
|
-
c.action do
|
47
|
-
|
69
|
+
c.action do |_, opts|
|
70
|
+
repo(opts).prune_files
|
48
71
|
end
|
49
72
|
end
|
50
73
|
|
data/circle.yml
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
machine:
|
2
|
+
environment:
|
3
|
+
AWS_ACCESS_KEY_ID: '1'
|
4
|
+
AWS_SECRET_ACCESS_KEY: '1'
|
1
5
|
dependencies:
|
2
6
|
override:
|
3
|
-
|
4
|
-
|
7
|
+
- 'for i in $(cat .circle-ruby) ; do rvm-exec $i gem update --system --no-doc || exit 1 ; done'
|
8
|
+
- 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle install || exit 1 ; done'
|
5
9
|
test:
|
6
10
|
override:
|
7
|
-
|
8
|
-
- 'rvm-exec 2.2.2 bundle exec rake'
|
11
|
+
- 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle exec rake || exit 1 ; done'
|
data/lib/s3repo.rb
CHANGED
data/lib/s3repo/base.rb
CHANGED
@@ -13,23 +13,19 @@ module S3Repo
|
|
13
13
|
def run(cmd)
|
14
14
|
results = `#{cmd} 2>&1`
|
15
15
|
return results if $CHILD_STATUS.success?
|
16
|
-
|
16
|
+
raise "Failed running #{cmd}:\n#{results}"
|
17
17
|
end
|
18
18
|
|
19
19
|
def bucket
|
20
|
-
@
|
21
|
-
return @bucket if @bucket
|
22
|
-
fail('No bucket given')
|
20
|
+
@options[:bucket] || raise('No bucket given')
|
23
21
|
end
|
24
22
|
|
25
23
|
def client
|
26
|
-
@
|
24
|
+
@options[:client] ||= Client.new(@options)
|
27
25
|
end
|
28
26
|
|
29
27
|
def file_cache
|
30
|
-
@file_cache ||= @options[:file_cache] || Cache.new(
|
31
|
-
client: client, tmpdir: @options[:tmpdir]
|
32
|
-
)
|
28
|
+
@file_cache ||= @options[:file_cache] || Cache.new(@options)
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
data/lib/s3repo/cache.rb
CHANGED
@@ -7,7 +7,6 @@ module S3Repo
|
|
7
7
|
# Cache object, stores S3 objects on disk
|
8
8
|
class Cache < Base
|
9
9
|
TMPDIRS = [
|
10
|
-
ENV['S3REPO_TMPDIR'],
|
11
10
|
ENV['TMPDIR'],
|
12
11
|
Dir.tmpdir,
|
13
12
|
'/tmp/s3repo'
|
@@ -18,20 +17,18 @@ module S3Repo
|
|
18
17
|
[partialdir, cachedir].each { |x| FileUtils.mkdir_p x }
|
19
18
|
end
|
20
19
|
|
21
|
-
def serve(key, refresh = true)
|
22
|
-
File.open(download(key, refresh), &:read)
|
23
|
-
rescue Aws::S3::Errors::NoSuchKey
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
20
|
def download(key, refresh = true)
|
30
21
|
path = expand_path key
|
31
22
|
get_object(key, path) if refresh || !cached?(path)
|
32
23
|
path
|
33
24
|
end
|
34
25
|
|
26
|
+
private
|
27
|
+
|
28
|
+
def file_cache
|
29
|
+
raise('Tried to call file_cache recursively')
|
30
|
+
end
|
31
|
+
|
35
32
|
def expand_path(key)
|
36
33
|
File.absolute_path(key, cachedir)
|
37
34
|
end
|
@@ -71,7 +68,13 @@ module S3Repo
|
|
71
68
|
end
|
72
69
|
|
73
70
|
def tmpdir
|
74
|
-
@tmpdir ||=
|
71
|
+
@tmpdir ||= Dir.mktmpdir 's3repo', tmpdir_root
|
72
|
+
end
|
73
|
+
|
74
|
+
def tmpdir_root
|
75
|
+
@tmpdir_root ||= File.absolute_path(
|
76
|
+
@options[:tmpdir] || TMPDIRS.compact.first
|
77
|
+
)
|
75
78
|
end
|
76
79
|
end
|
77
80
|
end
|
data/lib/s3repo/client.rb
CHANGED
@@ -5,21 +5,33 @@ module S3Repo
|
|
5
5
|
# AWS API client
|
6
6
|
class Client
|
7
7
|
def initialize(params = {})
|
8
|
-
@
|
9
|
-
@
|
8
|
+
@options = params
|
9
|
+
@api = Aws::S3::Client.new(region: region)
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def respond_to_missing?(method, include_all = false)
|
13
13
|
@api.respond_to?(method, include_all) || super
|
14
14
|
end
|
15
15
|
|
16
|
-
def upload
|
16
|
+
def upload(key, body)
|
17
17
|
puts "Uploading #{key}"
|
18
|
-
put_object key: key, body:
|
18
|
+
put_object key: key, body: body
|
19
|
+
end
|
20
|
+
|
21
|
+
def upload_file(key, path)
|
22
|
+
upload(key, File.open(path).read)
|
19
23
|
end
|
20
24
|
|
21
25
|
private
|
22
26
|
|
27
|
+
def region
|
28
|
+
@options[:region] || raise('AWS region not set')
|
29
|
+
end
|
30
|
+
|
31
|
+
def bucket
|
32
|
+
@options[:bucket] || raise('Bucket not set')
|
33
|
+
end
|
34
|
+
|
23
35
|
def method_missing(method, *args, &block)
|
24
36
|
return super unless @api.respond_to?(method)
|
25
37
|
define_singleton_method(method) do |*singleton_args|
|
@@ -30,10 +42,11 @@ module S3Repo
|
|
30
42
|
end
|
31
43
|
|
32
44
|
def build_params(args)
|
33
|
-
|
45
|
+
raise 'Too many arguments given' if args.size > 1
|
34
46
|
params = args.first || {}
|
35
|
-
|
36
|
-
|
47
|
+
raise 'Argument must be a hash' unless params.is_a? Hash
|
48
|
+
params[:bucket] ||= bucket
|
49
|
+
params
|
37
50
|
end
|
38
51
|
end
|
39
52
|
end
|
data/lib/s3repo/metadata.rb
CHANGED
@@ -5,11 +5,6 @@ module S3Repo
|
|
5
5
|
##
|
6
6
|
# Metadata object, represents repo's DB file
|
7
7
|
class Metadata < Base
|
8
|
-
def initialize(params = {})
|
9
|
-
super
|
10
|
-
FileUtils.mkdir_p db_dir
|
11
|
-
end
|
12
|
-
|
13
8
|
def add_packages(paths)
|
14
9
|
@db_path = nil
|
15
10
|
paths.each do |path|
|
@@ -29,38 +24,31 @@ module S3Repo
|
|
29
24
|
end
|
30
25
|
|
31
26
|
def update!
|
32
|
-
sign_db if
|
33
|
-
client.
|
27
|
+
sign_db if @options[:sign_db]
|
28
|
+
client.upload_file('repo.db', db_path)
|
29
|
+
client.upload_file('repo.db.tar.xz', db_path)
|
34
30
|
end
|
35
31
|
|
36
32
|
def packages
|
37
33
|
return @packages if @packages
|
38
|
-
cmd = "
|
34
|
+
cmd = "bsdtar tf #{db_path}"
|
39
35
|
@packages = run(cmd).split.map { |x| x.split('/').first }.uniq
|
40
36
|
end
|
41
37
|
|
42
38
|
private
|
43
39
|
|
44
|
-
def
|
45
|
-
|
46
|
-
client.upload!('repo.db.sig', "#{db_path}.sig")
|
47
|
-
end
|
48
|
-
|
49
|
-
def db_path
|
50
|
-
@db_path ||= download_db
|
40
|
+
def signer
|
41
|
+
@options[:signer] ||= Signer.new(@options)
|
51
42
|
end
|
52
43
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
tmpfile.path
|
44
|
+
def sign_db
|
45
|
+
sig_path = signer.sign(db_path)
|
46
|
+
client.upload_file('repo.db.sig', sig_path)
|
47
|
+
client.upload_file('repo.db.tar.xz.sig', sig_path)
|
58
48
|
end
|
59
49
|
|
60
|
-
def
|
61
|
-
@
|
62
|
-
@options[:tmpdir] || Cache::TMPDIRS.compact.first
|
63
|
-
)
|
50
|
+
def db_path
|
51
|
+
@db_path ||= file_cache.download('repo.db.tar.xz')
|
64
52
|
end
|
65
53
|
end
|
66
54
|
end
|
data/lib/s3repo/repo.rb
CHANGED
@@ -5,25 +5,23 @@ module S3Repo
|
|
5
5
|
##
|
6
6
|
# Repo object, represents an Arch repo inside an S3 bucket
|
7
7
|
class Repo < Base
|
8
|
-
def
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
12
|
-
def build_packages(paths, makepkg_flags = '')
|
8
|
+
def build_packages(paths)
|
13
9
|
paths.each do |path|
|
14
10
|
dir = File.dirname(path)
|
15
11
|
puts "Building #{File.basename(dir)}"
|
16
|
-
Dir.chdir(dir) { run "makepkg #{makepkg_flags}" }
|
12
|
+
Dir.chdir(dir) { run "makepkg #{@options[:makepkg_flags]}" }
|
17
13
|
end
|
18
14
|
end
|
19
15
|
|
20
16
|
def add_packages(paths)
|
21
17
|
paths.select! { |path| upload_package(path) }
|
22
18
|
metadata.add_packages(paths) unless paths.empty?
|
19
|
+
templates.update! unless paths.empty?
|
23
20
|
end
|
24
21
|
|
25
22
|
def remove_packages(packages)
|
26
23
|
metadata.remove_packages(packages)
|
24
|
+
templates.update!
|
27
25
|
end
|
28
26
|
|
29
27
|
def prune_files
|
@@ -47,19 +45,15 @@ module S3Repo
|
|
47
45
|
!packages.find { |x| x.key == key }.nil?
|
48
46
|
end
|
49
47
|
|
50
|
-
def serve(key)
|
51
|
-
refresh = !key.match(/\.pkg\.tar\.xz$/)
|
52
|
-
file_cache.serve(key, refresh)
|
53
|
-
end
|
54
|
-
|
55
48
|
private
|
56
49
|
|
57
50
|
def upload_package(path)
|
58
51
|
key = File.basename(path)
|
59
|
-
sig_key, sig_path = [key, path].map { |x| x + '.sig' }
|
60
52
|
return false if include? key
|
61
|
-
|
62
|
-
|
53
|
+
sig_path = signer.sign(path)
|
54
|
+
sig_key = key + '.sig'
|
55
|
+
client.upload_file(sig_key, sig_path) if @options[:sign_packages]
|
56
|
+
client.upload_file(key, path)
|
63
57
|
true
|
64
58
|
end
|
65
59
|
|
@@ -70,7 +64,15 @@ module S3Repo
|
|
70
64
|
end
|
71
65
|
|
72
66
|
def metadata
|
73
|
-
@metadata ||= Metadata.new(
|
67
|
+
@options[:metadata] ||= Metadata.new(@options)
|
68
|
+
end
|
69
|
+
|
70
|
+
def signer
|
71
|
+
@options[:signer] ||= Signer.new(@options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def templates
|
75
|
+
@templates ||= Templates.new(@options)
|
74
76
|
end
|
75
77
|
|
76
78
|
def package_cache
|