deb-s3-lock-fix 0.11.8.fix1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []