deb-s3-x 0.7.1.1
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 +15 -0
- data/README.md +126 -0
- data/bin/deb-s3 +9 -0
- data/lib/deb/s3.rb +6 -0
- data/lib/deb/s3/cli.rb +531 -0
- data/lib/deb/s3/manifest.rb +125 -0
- data/lib/deb/s3/package.rb +303 -0
- data/lib/deb/s3/release.rb +151 -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 +92 -0
- metadata +109 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "tempfile"
|
3
|
+
require "zlib"
|
4
|
+
require 'deb/s3/utils'
|
5
|
+
require 'deb/s3/package'
|
6
|
+
|
7
|
+
class Deb::S3::Manifest
|
8
|
+
include Deb::S3::Utils
|
9
|
+
|
10
|
+
attr_accessor :codename
|
11
|
+
attr_accessor :component
|
12
|
+
attr_accessor :cache_control
|
13
|
+
attr_accessor :architecture
|
14
|
+
|
15
|
+
attr_accessor :files
|
16
|
+
|
17
|
+
attr_reader :packages
|
18
|
+
attr_reader :packages_to_be_upload
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@packages = []
|
22
|
+
@packages_to_be_upload = []
|
23
|
+
@component = nil
|
24
|
+
@architecture = nil
|
25
|
+
@files = {}
|
26
|
+
@cache_control = ""
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def retrieve(codename, component, architecture, cache_control)
|
31
|
+
m = if s = Deb::S3::Utils.s3_read("dists/#{codename}/#{component}/binary-#{architecture}/Packages")
|
32
|
+
self.parse_packages(s)
|
33
|
+
else
|
34
|
+
self.new
|
35
|
+
end
|
36
|
+
|
37
|
+
m.codename = codename
|
38
|
+
m.component = component
|
39
|
+
m.architecture = architecture
|
40
|
+
m.cache_control = cache_control
|
41
|
+
m
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_packages(str)
|
45
|
+
m = self.new
|
46
|
+
str.split("\n\n").each do |s|
|
47
|
+
next if s.chomp.empty?
|
48
|
+
m.packages << Deb::S3::Package.parse_string(s)
|
49
|
+
end
|
50
|
+
m
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def add(pkg, preserve_versions, needs_uploading=true)
|
55
|
+
if preserve_versions
|
56
|
+
packages.delete_if { |p| p.name == pkg.name && p.full_version == pkg.full_version }
|
57
|
+
else
|
58
|
+
packages.delete_if { |p| p.name == pkg.name }
|
59
|
+
end
|
60
|
+
packages << pkg
|
61
|
+
packages_to_be_upload << pkg if needs_uploading
|
62
|
+
pkg
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete_package(pkg, versions=nil)
|
66
|
+
deleted = []
|
67
|
+
new_packages = @packages.select { |p|
|
68
|
+
# Include packages we didn't name
|
69
|
+
if p.name != pkg
|
70
|
+
p
|
71
|
+
# Also include the packages not matching a specified version
|
72
|
+
elsif (!versions.nil? and p.name == pkg and !versions.include?(p.version) and !versions.include?("#{p.version}-#{p.iteration}"))
|
73
|
+
p
|
74
|
+
end
|
75
|
+
}
|
76
|
+
deleted = @packages - new_packages
|
77
|
+
@packages = new_packages
|
78
|
+
deleted
|
79
|
+
end
|
80
|
+
|
81
|
+
def generate
|
82
|
+
@packages.collect { |pkg| pkg.generate }.join("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_to_s3
|
86
|
+
manifest = self.generate
|
87
|
+
|
88
|
+
# store any packages that need to be stored
|
89
|
+
@packages_to_be_upload.each do |pkg|
|
90
|
+
yield pkg.url_filename if block_given?
|
91
|
+
s3_store(pkg.filename, pkg.url_filename, 'application/octet-stream; charset=binary')
|
92
|
+
end
|
93
|
+
|
94
|
+
# generate the Packages file
|
95
|
+
pkgs_temp = Tempfile.new("Packages")
|
96
|
+
pkgs_temp.write manifest
|
97
|
+
pkgs_temp.close
|
98
|
+
f = "dists/#{@codename}/#{@component}/binary-#{@architecture}/Packages"
|
99
|
+
yield f if block_given?
|
100
|
+
s3_store(pkgs_temp.path, f, 'binary/octet-stream; charset=binary', self.cache_control)
|
101
|
+
@files["#{@component}/binary-#{@architecture}/Packages"] = hashfile(pkgs_temp.path)
|
102
|
+
pkgs_temp.unlink
|
103
|
+
|
104
|
+
# generate the Packages.gz file
|
105
|
+
gztemp = Tempfile.new("Packages.gz")
|
106
|
+
gztemp.close
|
107
|
+
Zlib::GzipWriter.open(gztemp.path) { |gz| gz.write manifest }
|
108
|
+
f = "dists/#{@codename}/#{@component}/binary-#{@architecture}/Packages.gz"
|
109
|
+
yield f if block_given?
|
110
|
+
s3_store(gztemp.path, f, 'application/x-gzip; charset=binary', self.cache_control)
|
111
|
+
@files["#{@component}/binary-#{@architecture}/Packages.gz"] = hashfile(gztemp.path)
|
112
|
+
gztemp.unlink
|
113
|
+
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
|
117
|
+
def hashfile(path)
|
118
|
+
{
|
119
|
+
:size => File.size(path),
|
120
|
+
:sha1 => Digest::SHA1.file(path).hexdigest,
|
121
|
+
:sha256 => Digest::SHA2.file(path).hexdigest,
|
122
|
+
:md5 => Digest::MD5.file(path).hexdigest
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "digest/sha1"
|
3
|
+
require "digest/sha2"
|
4
|
+
require "digest/md5"
|
5
|
+
require "socket"
|
6
|
+
require "tmpdir"
|
7
|
+
require "uri"
|
8
|
+
|
9
|
+
require 'deb/s3/utils'
|
10
|
+
|
11
|
+
class Deb::S3::Package
|
12
|
+
include Deb::S3::Utils
|
13
|
+
|
14
|
+
attr_accessor :name
|
15
|
+
attr_accessor :version
|
16
|
+
attr_accessor :epoch
|
17
|
+
attr_accessor :iteration
|
18
|
+
attr_accessor :maintainer
|
19
|
+
attr_accessor :vendor
|
20
|
+
attr_accessor :url
|
21
|
+
attr_accessor :category
|
22
|
+
attr_accessor :license
|
23
|
+
attr_accessor :architecture
|
24
|
+
attr_accessor :description
|
25
|
+
|
26
|
+
attr_accessor :dependencies
|
27
|
+
|
28
|
+
# Any other attributes specific to this package.
|
29
|
+
# This is where you'd put rpm, deb, or other specific attributes.
|
30
|
+
attr_accessor :attributes
|
31
|
+
|
32
|
+
# hashes
|
33
|
+
attr_accessor :url_filename
|
34
|
+
attr_accessor :sha1
|
35
|
+
attr_accessor :sha256
|
36
|
+
attr_accessor :md5
|
37
|
+
attr_accessor :size
|
38
|
+
|
39
|
+
attr_accessor :filename
|
40
|
+
|
41
|
+
class << self
|
42
|
+
include Deb::S3::Utils
|
43
|
+
|
44
|
+
def parse_file(package)
|
45
|
+
p = self.new
|
46
|
+
p.extract_info(extract_control(package))
|
47
|
+
p.apply_file_info(package)
|
48
|
+
p.filename = package
|
49
|
+
p
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_string(s)
|
53
|
+
p = self.new
|
54
|
+
p.extract_info(s)
|
55
|
+
p
|
56
|
+
end
|
57
|
+
|
58
|
+
def extract_control(package)
|
59
|
+
if system("which dpkg &> /dev/null")
|
60
|
+
`dpkg -f #{package}`
|
61
|
+
else
|
62
|
+
# ar fails to find the control.tar.gz tarball within the .deb
|
63
|
+
# on Mac OS. Try using ar to list the control file, if found,
|
64
|
+
# use ar to extract, otherwise attempt with tar which works on OS X.
|
65
|
+
extract_control_tarball_cmd = "ar p #{package} control.tar.gz"
|
66
|
+
|
67
|
+
begin
|
68
|
+
safesystem("ar t #{package} control.tar.gz &> /dev/null")
|
69
|
+
rescue SafeSystemError
|
70
|
+
warn "Failed to find control data in .deb with ar, trying tar."
|
71
|
+
extract_control_tarball_cmd = "tar zxf #{package} --to-stdout control.tar.gz"
|
72
|
+
end
|
73
|
+
|
74
|
+
Dir.mktmpdir do |path|
|
75
|
+
safesystem("#{extract_control_tarball_cmd} | tar -zxf - -C #{path}")
|
76
|
+
File.read(File.join(path, "control"))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize
|
83
|
+
@attributes = {}
|
84
|
+
|
85
|
+
# Reference
|
86
|
+
# http://www.debian.org/doc/manuals/maint-guide/first.en.html
|
87
|
+
# http://wiki.debian.org/DeveloperConfiguration
|
88
|
+
# https://github.com/jordansissel/fpm/issues/37
|
89
|
+
if ENV.include?("DEBEMAIL") and ENV.include?("DEBFULLNAME")
|
90
|
+
# Use DEBEMAIL and DEBFULLNAME as the default maintainer if available.
|
91
|
+
@maintainer = "#{ENV["DEBFULLNAME"]} <#{ENV["DEBEMAIL"]}>"
|
92
|
+
else
|
93
|
+
# TODO(sissel): Maybe support using 'git config' for a default as well?
|
94
|
+
# git config --get user.name, etc can be useful.
|
95
|
+
#
|
96
|
+
# Otherwise default to user@currenthost
|
97
|
+
@maintainer = "<#{ENV["USER"]}@#{Socket.gethostname}>"
|
98
|
+
end
|
99
|
+
|
100
|
+
@name = nil
|
101
|
+
@architecture = "native"
|
102
|
+
@description = "no description given"
|
103
|
+
@version = nil
|
104
|
+
@epoch = nil
|
105
|
+
@iteration = nil
|
106
|
+
@url = nil
|
107
|
+
@category = "default"
|
108
|
+
@license = "unknown"
|
109
|
+
@vendor = "none"
|
110
|
+
@sha1 = nil
|
111
|
+
@sha256 = nil
|
112
|
+
@md5 = nil
|
113
|
+
@size = nil
|
114
|
+
@filename = nil
|
115
|
+
@url_filename = nil
|
116
|
+
|
117
|
+
@dependencies = []
|
118
|
+
end
|
119
|
+
|
120
|
+
def full_version
|
121
|
+
return nil if [epoch, version, iteration].all?(&:nil?)
|
122
|
+
[[epoch, version].compact.join(":"), iteration].compact.join("-")
|
123
|
+
end
|
124
|
+
|
125
|
+
def filename=(f)
|
126
|
+
@filename = f
|
127
|
+
@filename
|
128
|
+
end
|
129
|
+
|
130
|
+
def url_filename
|
131
|
+
@url_filename || "pool/#{self.name[0]}/#{self.name[0..1]}/#{File.basename(self.filename)}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def url_filename_encoded
|
135
|
+
@url_filename || "pool/#{self.name[0]}/#{self.name[0..1]}/#{s3_escape(File.basename(self.filename))}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def generate
|
139
|
+
template("package.erb").result(binding)
|
140
|
+
end
|
141
|
+
|
142
|
+
# from fpm
|
143
|
+
def parse_depends(data)
|
144
|
+
return [] if data.nil? or data.empty?
|
145
|
+
# parse dependencies. Debian dependencies come in one of two forms:
|
146
|
+
# * name
|
147
|
+
# * name (op version)
|
148
|
+
# They are all on one line, separated by ", "
|
149
|
+
|
150
|
+
dep_re = /^([^ ]+)(?: \(([>=<]+) ([^)]+)\))?$/
|
151
|
+
return data.split(/, */).collect do |dep|
|
152
|
+
m = dep_re.match(dep)
|
153
|
+
if m
|
154
|
+
name, op, version = m.captures
|
155
|
+
# this is the proper form of dependency
|
156
|
+
if op && version && op != "" && version != ""
|
157
|
+
"#{name} (#{op} #{version})".strip
|
158
|
+
else
|
159
|
+
name.strip
|
160
|
+
end
|
161
|
+
else
|
162
|
+
# Assume normal form dependency, "name op version".
|
163
|
+
dep
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end # def parse_depends
|
167
|
+
|
168
|
+
# from fpm
|
169
|
+
def fix_dependency(dep)
|
170
|
+
# Deb dependencies are: NAME (OP VERSION), like "zsh (> 3.0)"
|
171
|
+
# Convert anything that looks like 'NAME OP VERSION' to this format.
|
172
|
+
if dep =~ /[\(,\|]/
|
173
|
+
# Don't "fix" ones that could appear well formed already.
|
174
|
+
else
|
175
|
+
# Convert ones that appear to be 'name op version'
|
176
|
+
name, op, version = dep.split(/ +/)
|
177
|
+
if !version.nil?
|
178
|
+
# Convert strings 'foo >= bar' to 'foo (>= bar)'
|
179
|
+
dep = "#{name} (#{debianize_op(op)} #{version})"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
name_re = /^[^ \(]+/
|
184
|
+
name = dep[name_re]
|
185
|
+
if name =~ /[A-Z]/
|
186
|
+
dep = dep.gsub(name_re) { |n| n.downcase }
|
187
|
+
end
|
188
|
+
|
189
|
+
if dep.include?("_")
|
190
|
+
dep = dep.gsub("_", "-")
|
191
|
+
end
|
192
|
+
|
193
|
+
# Convert gem ~> X.Y.Z to '>= X.Y.Z' and << X.Y+1.0
|
194
|
+
if dep =~ /\(~>/
|
195
|
+
name, version = dep.gsub(/[()~>]/, "").split(/ +/)[0..1]
|
196
|
+
nextversion = version.split(".").collect { |v| v.to_i }
|
197
|
+
l = nextversion.length
|
198
|
+
nextversion[l-2] += 1
|
199
|
+
nextversion[l-1] = 0
|
200
|
+
nextversion = nextversion.join(".")
|
201
|
+
return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
|
202
|
+
elsif (m = dep.match(/(\S+)\s+\(!= (.+)\)/))
|
203
|
+
# Append this to conflicts
|
204
|
+
self.conflicts += [dep.gsub(/!=/,"=")]
|
205
|
+
return []
|
206
|
+
elsif (m = dep.match(/(\S+)\s+\(= (.+)\)/)) and
|
207
|
+
self.attributes[:deb_ignore_iteration_in_dependencies?]
|
208
|
+
# Convert 'foo (= x)' to 'foo (>= x)' and 'foo (<< x+1)'
|
209
|
+
# but only when flag --ignore-iteration-in-dependencies is passed.
|
210
|
+
name, version = m[1..2]
|
211
|
+
nextversion = version.split('.').collect { |v| v.to_i }
|
212
|
+
nextversion[-1] += 1
|
213
|
+
nextversion = nextversion.join(".")
|
214
|
+
return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
|
215
|
+
else
|
216
|
+
# otherwise the dep is probably fine
|
217
|
+
return dep.rstrip
|
218
|
+
end
|
219
|
+
end # def fix_dependency
|
220
|
+
|
221
|
+
# from fpm
|
222
|
+
def extract_info(control)
|
223
|
+
fields = parse_control(control)
|
224
|
+
|
225
|
+
# Parse 'epoch:version-iteration' in the version string
|
226
|
+
full_version = fields.delete('Version')
|
227
|
+
if full_version !~ /^(?:([0-9]+):)?(.+?)(?:-(.*))?$/
|
228
|
+
raise "Unsupported version string '#{full_version}'"
|
229
|
+
end
|
230
|
+
self.epoch, self.version, self.iteration = $~.captures
|
231
|
+
|
232
|
+
self.architecture = fields.delete('Architecture')
|
233
|
+
self.category = fields.delete('Section')
|
234
|
+
self.license = fields.delete('License') || self.license
|
235
|
+
self.maintainer = fields.delete('Maintainer')
|
236
|
+
self.name = fields.delete('Package')
|
237
|
+
self.url = fields.delete('Homepage')
|
238
|
+
self.vendor = fields.delete('Vendor') || self.vendor
|
239
|
+
self.attributes[:deb_priority] = fields.delete('Priority')
|
240
|
+
self.attributes[:deb_origin] = fields.delete('Origin')
|
241
|
+
self.attributes[:deb_installed_size] = fields.delete('Installed-Size')
|
242
|
+
|
243
|
+
# Packages manifest fields
|
244
|
+
filename = fields.delete('Filename')
|
245
|
+
self.url_filename = filename && URI.unescape(filename)
|
246
|
+
self.sha1 = fields.delete('SHA1')
|
247
|
+
self.sha256 = fields.delete('SHA256')
|
248
|
+
self.md5 = fields.delete('MD5sum')
|
249
|
+
self.size = fields.delete('Size')
|
250
|
+
self.description = fields.delete('Description')
|
251
|
+
|
252
|
+
#self.config_files = config_files
|
253
|
+
|
254
|
+
self.dependencies += Array(parse_depends(fields.delete('Depends')))
|
255
|
+
|
256
|
+
self.attributes[:deb_recommends] = fields.delete('Recommends')
|
257
|
+
self.attributes[:deb_suggests] = fields.delete('Suggests')
|
258
|
+
self.attributes[:deb_enhances] = fields.delete('Enhances')
|
259
|
+
self.attributes[:deb_pre_depends] = fields.delete('Pre-Depends')
|
260
|
+
|
261
|
+
self.attributes[:deb_breaks] = fields.delete('Breaks')
|
262
|
+
self.attributes[:deb_conflicts] = fields.delete('Conflicts')
|
263
|
+
self.attributes[:deb_provides] = fields.delete('Provides')
|
264
|
+
self.attributes[:deb_replaces] = fields.delete('Replaces')
|
265
|
+
|
266
|
+
self.attributes[:deb_field] = Hash[fields.map { |k, v|
|
267
|
+
[k.sub(/\AX[BCS]{0,3}-/, ''), v]
|
268
|
+
}]
|
269
|
+
|
270
|
+
end # def extract_info
|
271
|
+
|
272
|
+
def apply_file_info(file)
|
273
|
+
self.size = File.size(file)
|
274
|
+
self.sha1 = Digest::SHA1.file(file).hexdigest
|
275
|
+
self.sha256 = Digest::SHA2.file(file).hexdigest
|
276
|
+
self.md5 = Digest::MD5.file(file).hexdigest
|
277
|
+
end
|
278
|
+
|
279
|
+
def parse_control(control)
|
280
|
+
field = nil
|
281
|
+
value = ""
|
282
|
+
{}.tap do |fields|
|
283
|
+
control.each_line do |line|
|
284
|
+
if line =~ /^(\s+)(\S.*)$/
|
285
|
+
indent, rest = $1, $2
|
286
|
+
# Continuation
|
287
|
+
if indent.size == 1 && rest == "."
|
288
|
+
value << "\n"
|
289
|
+
rest = ""
|
290
|
+
elsif value.size > 0
|
291
|
+
value << "\n"
|
292
|
+
end
|
293
|
+
value << rest
|
294
|
+
elsif line =~ /^([-\w]+):(.*)$/
|
295
|
+
fields[field] = value if field
|
296
|
+
field, value = $1, $2.strip
|
297
|
+
end
|
298
|
+
end
|
299
|
+
fields[field] = value if field
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
@@ -0,0 +1,151 @@
|
|
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
|
+
rel.codename = codename
|
35
|
+
rel.origin = origin unless origin.nil?
|
36
|
+
rel.suite = suite unless suite.nil?
|
37
|
+
end
|
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, 'binary/octet-stream; charset=binary', 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} #{Deb::S3::Utils.gpg_options} -b #{release_tmp.path}")
|
107
|
+
local_file = release_tmp.path+".asc"
|
108
|
+
remote_file = self.filename+".gpg"
|
109
|
+
yield remote_file if block_given?
|
110
|
+
raise "Unable to locate Release signature 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 Release file failed."
|
115
|
+
end
|
116
|
+
else
|
117
|
+
# remove an existing Release.gpg, if it was there
|
118
|
+
s3_remove(self.filename+".gpg")
|
119
|
+
end
|
120
|
+
|
121
|
+
release_tmp.unlink
|
122
|
+
end
|
123
|
+
|
124
|
+
def update_manifest(manifest)
|
125
|
+
self.components << manifest.component unless self.components.include?(manifest.component)
|
126
|
+
self.architectures << manifest.architecture unless self.architectures.include?(manifest.architecture)
|
127
|
+
self.files.merge!(manifest.files)
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_others
|
131
|
+
to_apply = []
|
132
|
+
self.components.each do |comp|
|
133
|
+
%w(amd64 i386).each do |arch|
|
134
|
+
next if self.files.has_key?("#{comp}/binary-#{arch}/Packages")
|
135
|
+
|
136
|
+
m = Deb::S3::Manifest.new
|
137
|
+
m.codename = self.codename
|
138
|
+
m.component = comp
|
139
|
+
m.architecture = arch
|
140
|
+
if block_given?
|
141
|
+
m.write_to_s3 { |f| yield f }
|
142
|
+
else
|
143
|
+
m.write_to_s3
|
144
|
+
end
|
145
|
+
to_apply << m
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
to_apply.each { |m| self.update_manifest(m) }
|
150
|
+
end
|
151
|
+
end
|