deb-s3-patched 0.11.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.
@@ -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 != "" ? "--default-key=#{Deb::S3::Utils.signing_key}" : ""
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.exists?(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.exists?(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_encoded(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 -%>
@@ -0,0 +1,117 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require "base64"
3
+ require "digest/md5"
4
+ require "erb"
5
+ require "tmpdir"
6
+
7
+ module Deb::S3::Utils
8
+ module_function
9
+ def s3; @s3 end
10
+ def s3= v; @s3 = v end
11
+ def bucket; @bucket end
12
+ def bucket= v; @bucket = v end
13
+ def access_policy; @access_policy end
14
+ def access_policy= v; @access_policy = v end
15
+ def signing_key; @signing_key end
16
+ def signing_key= v; @signing_key = v end
17
+ def gpg_options; @gpg_options end
18
+ def gpg_options= v; @gpg_options = v end
19
+ def prefix; @prefix end
20
+ def prefix= v; @prefix = v end
21
+ def encryption; @encryption end
22
+ def encryption= v; @encryption = v end
23
+
24
+ class SafeSystemError < RuntimeError; end
25
+ class AlreadyExistsError < RuntimeError; end
26
+
27
+ def safesystem(*args)
28
+ success = system(*args)
29
+ if !success
30
+ raise SafeSystemError, "'system(#{args.inspect})' failed with error code: #{$?.exitstatus}"
31
+ end
32
+ return success
33
+ end
34
+
35
+ def debianize_op(op)
36
+ # Operators in debian packaging are <<, <=, =, >= and >>
37
+ # So any operator like < or > must be replaced
38
+ {:< => "<<", :> => ">>"}[op.to_sym] or op
39
+ end
40
+
41
+ def template(path)
42
+ template_file = File.join(File.dirname(__FILE__), "templates", path)
43
+ template_code = File.read(template_file)
44
+ ERB.new(template_code, nil, "-")
45
+ end
46
+
47
+ def s3_path(path)
48
+ File.join(*[Deb::S3::Utils.prefix, path].compact)
49
+ end
50
+
51
+ # from fog, Fog::AWS.escape
52
+ def s3_escape(string)
53
+ string.gsub(/([^a-zA-Z0-9_.\-~+]+)/) {
54
+ "%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
55
+ }
56
+ end
57
+
58
+ def s3_exists?(path)
59
+ Deb::S3::Utils.s3.head_object(
60
+ :bucket => Deb::S3::Utils.bucket,
61
+ :key => s3_path(path),
62
+ )
63
+ rescue Aws::S3::Errors::NotFound
64
+ false
65
+ end
66
+
67
+ def s3_read(path)
68
+ Deb::S3::Utils.s3.get_object(
69
+ :bucket => Deb::S3::Utils.bucket,
70
+ :key => s3_path(path),
71
+ )[:body].read
72
+ rescue Aws::S3::Errors::NoSuchKey
73
+ false
74
+ end
75
+
76
+ def s3_store(path, filename=nil, content_type='application/octet-stream; charset=binary', cache_control=nil, fail_if_exists=false)
77
+ filename = File.basename(path) unless filename
78
+ obj = s3_exists?(filename)
79
+
80
+ file_md5 = Digest::MD5.file(path)
81
+
82
+ # check if the object already exists
83
+ if obj != false
84
+ return if (file_md5.to_s == obj[:etag].gsub('"', '') or file_md5.to_s == obj[:metadata]['md5'])
85
+ raise AlreadyExistsError, "file #{filename} already exists with different contents" if fail_if_exists
86
+ end
87
+
88
+ options = {
89
+ :bucket => Deb::S3::Utils.bucket,
90
+ :key => s3_path(filename),
91
+ :acl => Deb::S3::Utils.access_policy,
92
+ :content_type => content_type,
93
+ :metadata => { "md5" => file_md5.to_s },
94
+ }
95
+ if !cache_control.nil?
96
+ options[:cache_control] = cache_control
97
+ end
98
+
99
+ # specify if encryption is required
100
+ options[:server_side_encryption] = "AES256" if Deb::S3::Utils.encryption
101
+
102
+ # upload the file
103
+ File.open(path) do |f|
104
+ options[:body] = f
105
+ Deb::S3::Utils.s3.put_object(options)
106
+ end
107
+ end
108
+
109
+ def s3_remove(path)
110
+ if s3_exists?(path)
111
+ Deb::S3::Utils.s3.delete_object(
112
+ :bucket =>Deb::S3::Utils.bucket,
113
+ :key => s3_path(path),
114
+ )
115
+ end
116
+ end
117
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deb-s3-patched
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.0
5
+ platform: ruby
6
+ authors:
7
+ - Gunter Grodotzki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-28 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: 0.19.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.19.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
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: Easily create and manage an APT repository on S3.
70
+ email: gunter@grodotzki.com
71
+ executables:
72
+ - deb-s3
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - README.md
77
+ - bin/deb-s3
78
+ - lib/deb/s3.rb
79
+ - lib/deb/s3/cli.rb
80
+ - lib/deb/s3/lock.rb
81
+ - lib/deb/s3/manifest.rb
82
+ - lib/deb/s3/package.rb
83
+ - lib/deb/s3/release.rb
84
+ - lib/deb/s3/templates/package.erb
85
+ - lib/deb/s3/templates/release.erb
86
+ - lib/deb/s3/utils.rb
87
+ homepage: https://github.com/lifeofguenter/deb-s3
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 2.5.7
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubygems_version: 3.0.8
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Easily create and manage an APT repository on S3.
110
+ test_files: []