deb-s3-lock-fix 0.11.8.fix1
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 +7 -0
- data/README.md +284 -0
- data/bin/deb-s3 +10 -0
- data/lib/deb/s3/cli.rb +763 -0
- data/lib/deb/s3/lock.rb +125 -0
- data/lib/deb/s3/manifest.rb +144 -0
- data/lib/deb/s3/package.rb +309 -0
- data/lib/deb/s3/release.rb +161 -0
- data/lib/deb/s3/templates/package.erb +66 -0
- data/lib/deb/s3/templates/release.erb +20 -0
- data/lib/deb/s3/utils.rb +115 -0
- data/lib/deb/s3.rb +6 -0
- metadata +111 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
class Deb::S3::Release
|
5
|
+
include Deb::S3::Utils
|
6
|
+
|
7
|
+
attr_accessor :codename
|
8
|
+
attr_accessor :origin
|
9
|
+
attr_accessor :suite
|
10
|
+
attr_accessor :architectures
|
11
|
+
attr_accessor :components
|
12
|
+
attr_accessor :cache_control
|
13
|
+
|
14
|
+
attr_accessor :files
|
15
|
+
attr_accessor :policy
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@origin = nil
|
19
|
+
@suite = nil
|
20
|
+
@codename = nil
|
21
|
+
@architectures = []
|
22
|
+
@components = []
|
23
|
+
@cache_control = ""
|
24
|
+
@files = {}
|
25
|
+
@policy = :public_read
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def retrieve(codename, origin=nil, suite=nil, cache_control=nil)
|
30
|
+
if s = Deb::S3::Utils.s3_read("dists/#{codename}/Release")
|
31
|
+
rel = self.parse_release(s)
|
32
|
+
else
|
33
|
+
rel = self.new
|
34
|
+
end
|
35
|
+
rel.codename = codename
|
36
|
+
rel.origin = origin unless origin.nil?
|
37
|
+
rel.suite = suite unless suite.nil?
|
38
|
+
rel.cache_control = cache_control
|
39
|
+
rel
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_release(str)
|
43
|
+
rel = self.new
|
44
|
+
rel.parse(str)
|
45
|
+
rel
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def filename
|
50
|
+
"dists/#{@codename}/Release"
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse(str)
|
54
|
+
parse = lambda do |field|
|
55
|
+
value = str[/^#{field}: .*/]
|
56
|
+
if value.nil?
|
57
|
+
return nil
|
58
|
+
else
|
59
|
+
return value.split(": ",2).last
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# grab basic fields
|
64
|
+
self.codename = parse.call("Codename")
|
65
|
+
self.origin = parse.call("Origin") || nil
|
66
|
+
self.suite = parse.call("Suite") || nil
|
67
|
+
self.architectures = (parse.call("Architectures") || "").split(/\s+/)
|
68
|
+
self.components = (parse.call("Components") || "").split(/\s+/)
|
69
|
+
|
70
|
+
# find all the hashes
|
71
|
+
str.scan(/^\s+([^\s]+)\s+(\d+)\s+(.+)$/).each do |(hash,size,name)|
|
72
|
+
self.files[name] ||= { :size => size.to_i }
|
73
|
+
case hash.length
|
74
|
+
when 32
|
75
|
+
self.files[name][:md5] = hash
|
76
|
+
when 40
|
77
|
+
self.files[name][:sha1] = hash
|
78
|
+
when 64
|
79
|
+
self.files[name][:sha256] = hash
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def generate
|
85
|
+
template("release.erb").result(binding)
|
86
|
+
end
|
87
|
+
|
88
|
+
def write_to_s3
|
89
|
+
# validate some other files are present
|
90
|
+
if block_given?
|
91
|
+
self.validate_others { |f| yield f }
|
92
|
+
else
|
93
|
+
self.validate_others
|
94
|
+
end
|
95
|
+
|
96
|
+
# generate the Release file
|
97
|
+
release_tmp = Tempfile.new("Release")
|
98
|
+
release_tmp.puts self.generate
|
99
|
+
release_tmp.close
|
100
|
+
yield self.filename if block_given?
|
101
|
+
s3_store(release_tmp.path, self.filename, 'text/plain; charset=utf-8', self.cache_control)
|
102
|
+
|
103
|
+
# sign the file, if necessary
|
104
|
+
if Deb::S3::Utils.signing_key
|
105
|
+
key_param = Deb::S3::Utils.signing_key.any? ? "-u #{Deb::S3::Utils.signing_key.join(" -u ")}" : ""
|
106
|
+
if system("gpg -a #{key_param} --digest-algo SHA256 #{Deb::S3::Utils.gpg_options} -s --clearsign #{release_tmp.path}")
|
107
|
+
local_file = release_tmp.path+".asc"
|
108
|
+
remote_file = "dists/#{@codename}/InRelease"
|
109
|
+
yield remote_file if block_given?
|
110
|
+
raise "Unable to locate InRelease file" unless File.exist?(local_file)
|
111
|
+
s3_store(local_file, remote_file, 'application/pgp-signature; charset=us-ascii', self.cache_control)
|
112
|
+
File.unlink(local_file)
|
113
|
+
else
|
114
|
+
raise "Signing the InRelease file failed."
|
115
|
+
end
|
116
|
+
if system("gpg -a #{key_param} --digest-algo SHA256 #{Deb::S3::Utils.gpg_options} -b #{release_tmp.path}")
|
117
|
+
local_file = release_tmp.path+".asc"
|
118
|
+
remote_file = self.filename+".gpg"
|
119
|
+
yield remote_file if block_given?
|
120
|
+
raise "Unable to locate Release signature file" unless File.exist?(local_file)
|
121
|
+
s3_store(local_file, remote_file, 'application/pgp-signature; charset=us-ascii', self.cache_control)
|
122
|
+
File.unlink(local_file)
|
123
|
+
else
|
124
|
+
raise "Signing the Release file failed."
|
125
|
+
end
|
126
|
+
else
|
127
|
+
# remove an existing Release.gpg, if it was there
|
128
|
+
s3_remove(self.filename+".gpg")
|
129
|
+
end
|
130
|
+
|
131
|
+
release_tmp.unlink
|
132
|
+
end
|
133
|
+
|
134
|
+
def update_manifest(manifest)
|
135
|
+
self.components << manifest.component unless self.components.include?(manifest.component)
|
136
|
+
self.architectures << manifest.architecture unless self.architectures.include?(manifest.architecture)
|
137
|
+
self.files.merge!(manifest.files)
|
138
|
+
end
|
139
|
+
|
140
|
+
def validate_others
|
141
|
+
to_apply = []
|
142
|
+
self.components.each do |comp|
|
143
|
+
%w(amd64 i386 armhf).each do |arch|
|
144
|
+
next if self.files.has_key?("#{comp}/binary-#{arch}/Packages")
|
145
|
+
|
146
|
+
m = Deb::S3::Manifest.new
|
147
|
+
m.codename = self.codename
|
148
|
+
m.component = comp
|
149
|
+
m.architecture = arch
|
150
|
+
if block_given?
|
151
|
+
m.write_to_s3 { |f| yield f }
|
152
|
+
else
|
153
|
+
m.write_to_s3
|
154
|
+
end
|
155
|
+
to_apply << m
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
to_apply.each { |m| self.update_manifest(m) }
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
Package: <%= name %>
|
2
|
+
Version: <%= "#{epoch}:" if epoch %><%= version %><%= "-" + iteration.to_s if iteration %>
|
3
|
+
License: <%= license %>
|
4
|
+
Vendor: <%= vendor %>
|
5
|
+
Architecture: <%= architecture %>
|
6
|
+
Maintainer: <%= maintainer %>
|
7
|
+
Installed-Size: <%= attributes[:deb_installed_size] %>
|
8
|
+
<% if !dependencies.empty? and !attributes[:no_depends?] -%>
|
9
|
+
Depends: <%= dependencies.collect { |d| fix_dependency(d) }.flatten.join(", ") %>
|
10
|
+
<% end -%>
|
11
|
+
<% if attributes[:deb_conflicts] -%>
|
12
|
+
Conflicts: <%= attributes[:deb_conflicts] %>
|
13
|
+
<% end -%>
|
14
|
+
<% if attributes[:deb_breaks] -%>
|
15
|
+
Breaks: <%= attributes[:deb_breaks] %>
|
16
|
+
<% end -%>
|
17
|
+
<% if attributes[:deb_pre_depends] -%>
|
18
|
+
Pre-Depends: <%= attributes[:deb_pre_depends] %>
|
19
|
+
<% end -%>
|
20
|
+
<% if attributes[:deb_provides] -%>
|
21
|
+
<%# Turn each provides from 'foo = 123' to simply 'foo' because Debian :\ -%>
|
22
|
+
<%# http://www.debian.org/doc/debian-policy/ch-relationships.html -%>
|
23
|
+
Provides: <%= attributes[:deb_provides] %>
|
24
|
+
<% end -%>
|
25
|
+
<% if attributes[:deb_replaces] -%>
|
26
|
+
Replaces: <%= attributes[:deb_replaces] %>
|
27
|
+
<% end -%>
|
28
|
+
<% if attributes[:deb_recommends] -%>
|
29
|
+
Recommends: <%= attributes[:deb_recommends] %>
|
30
|
+
<% end -%>
|
31
|
+
<% if attributes[:deb_suggests] -%>
|
32
|
+
Suggests: <%= attributes[:deb_suggests] %>
|
33
|
+
<% end -%>
|
34
|
+
<% if attributes[:deb_enhances] -%>
|
35
|
+
Enhances: <%= attributes[:deb_enhances] %>
|
36
|
+
<% end -%>
|
37
|
+
Section: <%= category %>
|
38
|
+
<% if attributes[:deb_origin] -%>
|
39
|
+
Origin: <%= attributes[:deb_origin] %>
|
40
|
+
<% end -%>
|
41
|
+
Priority: <%= attributes[:deb_priority] %>
|
42
|
+
Homepage: <%= url or "http://nourlgiven.example.com/" %>
|
43
|
+
Filename: <%= url_filename(codename) %>
|
44
|
+
<% if size -%>
|
45
|
+
Size: <%= size %>
|
46
|
+
<% end -%>
|
47
|
+
<% if sha1 -%>
|
48
|
+
SHA1: <%= sha1 %>
|
49
|
+
<% end -%>
|
50
|
+
<% if sha256 -%>
|
51
|
+
SHA256: <%= sha256 %>
|
52
|
+
<% end -%>
|
53
|
+
<% if md5 -%>
|
54
|
+
MD5sum: <%= md5 %>
|
55
|
+
<% end -%>
|
56
|
+
<% lines = (description or "no description given").split("\n") -%>
|
57
|
+
<% firstline, *remainder = lines -%>
|
58
|
+
Description: <%= firstline %>
|
59
|
+
<% if remainder.any? -%>
|
60
|
+
<%= remainder.collect { |l| l =~ /^ *$/ ? " ." : " #{l}" }.join("\n") %>
|
61
|
+
<% end -%>
|
62
|
+
<% if attributes[:deb_field] -%>
|
63
|
+
<% attributes[:deb_field].each do |field, value| -%>
|
64
|
+
<%= field %>: <%= value %>
|
65
|
+
<% end -%>
|
66
|
+
<% end -%>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% if origin -%>
|
2
|
+
Origin: <%= origin %>
|
3
|
+
<% end -%>
|
4
|
+
Codename: <%= codename %>
|
5
|
+
Date: <%= Time.now.utc.strftime("%a, %d %b %Y %T %Z") %>
|
6
|
+
Architectures: <%= architectures.join(" ") %>
|
7
|
+
Components: <%= components.join(" ") %>
|
8
|
+
Suite: <%= suite %>
|
9
|
+
MD5Sum:
|
10
|
+
<% files.sort.each do |f,p| -%>
|
11
|
+
<%= p[:md5] %> <%= p[:size].to_s.rjust(16) %> <%= f %>
|
12
|
+
<% end -%>
|
13
|
+
SHA1:
|
14
|
+
<% files.sort.each do |f,p| -%>
|
15
|
+
<%= p[:sha1] %> <%= p[:size].to_s.rjust(16) %> <%= f %>
|
16
|
+
<% end -%>
|
17
|
+
SHA256:
|
18
|
+
<% files.sort.each do |f,p| -%>
|
19
|
+
<%= p[:sha256] %> <%= p[:size].to_s.rjust(16) %> <%= f %>
|
20
|
+
<% end -%>
|
data/lib/deb/s3/utils.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "digest/md5"
|
3
|
+
require "erb"
|
4
|
+
|
5
|
+
module Deb::S3::Utils
|
6
|
+
module_function
|
7
|
+
def s3; @s3 end
|
8
|
+
def s3= v; @s3 = v end
|
9
|
+
def bucket; @bucket end
|
10
|
+
def bucket= v; @bucket = v end
|
11
|
+
def access_policy; @access_policy end
|
12
|
+
def access_policy= v; @access_policy = v end
|
13
|
+
def signing_key; @signing_key end
|
14
|
+
def signing_key= v; @signing_key = v end
|
15
|
+
def gpg_options; @gpg_options end
|
16
|
+
def gpg_options= v; @gpg_options = v end
|
17
|
+
def prefix; @prefix end
|
18
|
+
def prefix= v; @prefix = v end
|
19
|
+
def encryption; @encryption end
|
20
|
+
def encryption= v; @encryption = v end
|
21
|
+
|
22
|
+
class SafeSystemError < RuntimeError; end
|
23
|
+
class AlreadyExistsError < RuntimeError; end
|
24
|
+
|
25
|
+
def safesystem(*args)
|
26
|
+
success = system(*args)
|
27
|
+
if !success
|
28
|
+
raise SafeSystemError, "'system(#{args.inspect})' failed with error code: #{$?.exitstatus}"
|
29
|
+
end
|
30
|
+
return success
|
31
|
+
end
|
32
|
+
|
33
|
+
def debianize_op(op)
|
34
|
+
# Operators in debian packaging are <<, <=, =, >= and >>
|
35
|
+
# So any operator like < or > must be replaced
|
36
|
+
{:< => "<<", :> => ">>"}[op.to_sym] or op
|
37
|
+
end
|
38
|
+
|
39
|
+
def template(path)
|
40
|
+
template_file = File.join(File.dirname(__FILE__), "templates", path)
|
41
|
+
template_code = File.read(template_file)
|
42
|
+
ERB.new(template_code, trim_mode: "-")
|
43
|
+
end
|
44
|
+
|
45
|
+
def s3_path(path)
|
46
|
+
File.join(*[Deb::S3::Utils.prefix, path].compact)
|
47
|
+
end
|
48
|
+
|
49
|
+
# from fog, Fog::AWS.escape
|
50
|
+
def s3_escape(string)
|
51
|
+
string.gsub(/([^a-zA-Z0-9_.\-~+]+)/) {
|
52
|
+
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def s3_exists?(path)
|
57
|
+
Deb::S3::Utils.s3.head_object(
|
58
|
+
:bucket => Deb::S3::Utils.bucket,
|
59
|
+
:key => s3_path(path),
|
60
|
+
)
|
61
|
+
rescue Aws::S3::Errors::NotFound
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
def s3_read(path)
|
66
|
+
Deb::S3::Utils.s3.get_object(
|
67
|
+
:bucket => Deb::S3::Utils.bucket,
|
68
|
+
:key => s3_path(path),
|
69
|
+
)[:body].read
|
70
|
+
rescue Aws::S3::Errors::NoSuchKey
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def s3_store(path, filename=nil, content_type='application/octet-stream; charset=binary', cache_control=nil, fail_if_exists=false)
|
75
|
+
filename = File.basename(path) unless filename
|
76
|
+
obj = s3_exists?(filename)
|
77
|
+
|
78
|
+
file_md5 = Digest::MD5.file(path)
|
79
|
+
|
80
|
+
# check if the object already exists
|
81
|
+
if obj != false
|
82
|
+
return if (file_md5.to_s == obj[:etag].gsub('"', '') or file_md5.to_s == obj[:metadata]['md5'])
|
83
|
+
raise AlreadyExistsError, "file #{filename} already exists with different contents" if fail_if_exists
|
84
|
+
end
|
85
|
+
|
86
|
+
options = {
|
87
|
+
:bucket => Deb::S3::Utils.bucket,
|
88
|
+
:key => s3_path(filename),
|
89
|
+
:acl => Deb::S3::Utils.access_policy,
|
90
|
+
:content_type => content_type,
|
91
|
+
:metadata => { "md5" => file_md5.to_s },
|
92
|
+
}
|
93
|
+
if !cache_control.nil?
|
94
|
+
options[:cache_control] = cache_control
|
95
|
+
end
|
96
|
+
|
97
|
+
# specify if encryption is required
|
98
|
+
options[:server_side_encryption] = "AES256" if Deb::S3::Utils.encryption
|
99
|
+
|
100
|
+
# upload the file
|
101
|
+
File.open(path) do |f|
|
102
|
+
options[:body] = f
|
103
|
+
Deb::S3::Utils.s3.put_object(options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def s3_remove(path)
|
108
|
+
if s3_exists?(path)
|
109
|
+
Deb::S3::Utils.s3.delete_object(
|
110
|
+
:bucket =>Deb::S3::Utils.bucket,
|
111
|
+
:key => s3_path(path),
|
112
|
+
)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/deb/s3.rb
ADDED
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deb-s3-lock-fix
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.11.8.fix1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Braeden Wolf & Ken Robertson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-09-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk-s3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '11'
|
69
|
+
description: Fork of deb-s3 with a specific fix for locking. Original work by Ken
|
70
|
+
Robertson.
|
71
|
+
email: braedenwolf@outlook.com & ken@invalidlogic.com
|
72
|
+
executables:
|
73
|
+
- deb-s3
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- README.md
|
78
|
+
- bin/deb-s3
|
79
|
+
- lib/deb/s3.rb
|
80
|
+
- lib/deb/s3/cli.rb
|
81
|
+
- lib/deb/s3/lock.rb
|
82
|
+
- lib/deb/s3/manifest.rb
|
83
|
+
- lib/deb/s3/package.rb
|
84
|
+
- lib/deb/s3/release.rb
|
85
|
+
- lib/deb/s3/templates/package.erb
|
86
|
+
- lib/deb/s3/templates/release.erb
|
87
|
+
- lib/deb/s3/utils.rb
|
88
|
+
homepage: https://github.com/braedenwolf/deb-s3-lock-fix
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 2.7.0
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">"
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 1.3.1
|
106
|
+
requirements: []
|
107
|
+
rubygems_version: 3.1.2
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: Easily create and manage an APT repository on S3 (with specific lock fix).
|
111
|
+
test_files: []
|