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.
@@ -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 -%>
@@ -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
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Deb
3
+ module S3
4
+ VERSION = "0.11.8"
5
+ end
6
+ end
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: []