deb-s3 0.6.2 → 0.7.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.
- checksums.yaml +4 -4
- data/README.md +1 -6
- data/lib/deb/s3.rb +2 -1
- data/lib/deb/s3/cli.rb +236 -31
- data/lib/deb/s3/manifest.rb +15 -10
- data/lib/deb/s3/package.rb +65 -56
- data/lib/deb/s3/release.rb +17 -5
- data/lib/deb/s3/templates/package.erb +15 -9
- data/lib/deb/s3/templates/release.erb +4 -0
- data/lib/deb/s3/utils.rb +14 -3
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c95a36618dfc6b8a2853b54c17101ae09140b3c
|
4
|
+
data.tar.gz: 5e14dda3916cd69e1e4eb3e5e26dd78b0f5cd94e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa1ce1124db8ca4a388e7a8141c88ccf6b262fe5d0f3f91a124e4311a255008b7f3b2c50c167154bbbeb31d614c380d22da02f0b8f7a9d8708ef968144795e38
|
7
|
+
data.tar.gz: c99fbb92d14f98a643b3f21d337aef9c6f773b98385eca3db3584480dd1369af2fff7c0fb93128f7ef624a488b9b50d37439176fd72697e4b8f14e53ed6a9f49
|
data/README.md
CHANGED
@@ -22,7 +22,7 @@ With `deb-s3`, there is no need for this. `deb-s3` features:
|
|
22
22
|
* Updates it with the new package, replacing the existing entry if already
|
23
23
|
there or adding a new one if not.
|
24
24
|
* Uploads the package itself, the Packages manifest, and the Packages.gz
|
25
|
-
manifest.
|
25
|
+
manifest. It will skip the uploading if the package is already there.
|
26
26
|
* Updates the Release file with the new hashes and file sizes.
|
27
27
|
|
28
28
|
## Getting Started
|
@@ -124,8 +124,3 @@ Options:
|
|
124
124
|
Verifies that the files in the package manifests exist
|
125
125
|
```
|
126
126
|
|
127
|
-
## TODO
|
128
|
-
|
129
|
-
This is still experimental. These are several things to be done:
|
130
|
-
|
131
|
-
* Don't re-upload a package if it already exists and has the same hashes.
|
data/lib/deb/s3.rb
CHANGED
data/lib/deb/s3/cli.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require "aws"
|
2
3
|
require "thor"
|
3
4
|
|
@@ -20,6 +21,15 @@ class Deb::S3::CLI < Thor
|
|
20
21
|
:type => :string,
|
21
22
|
:desc => "The path prefix to use when storing on S3."
|
22
23
|
|
24
|
+
class_option :origin,
|
25
|
+
:type => :string,
|
26
|
+
:aliases => "-o",
|
27
|
+
:desc => "The origin to use in the repository Release file."
|
28
|
+
|
29
|
+
class_option :suite,
|
30
|
+
:type => :string,
|
31
|
+
:desc => "The suite to use in the repository Release file."
|
32
|
+
|
23
33
|
class_option :codename,
|
24
34
|
:default => "stable",
|
25
35
|
:type => :string,
|
@@ -77,6 +87,22 @@ class Deb::S3::CLI < Thor
|
|
77
87
|
:type => :string,
|
78
88
|
:desc => "Additional command line options to pass to GPG when signing"
|
79
89
|
|
90
|
+
class_option :encryption,
|
91
|
+
:default => false,
|
92
|
+
:type => :boolean,
|
93
|
+
:aliases => "-e",
|
94
|
+
:desc => "Use S3 server side encryption"
|
95
|
+
|
96
|
+
class_option :quiet,
|
97
|
+
:type => :boolean,
|
98
|
+
:aliases => "-q",
|
99
|
+
:desc => "Doesn't output information, just returns status appropriately."
|
100
|
+
|
101
|
+
class_option :cache_control,
|
102
|
+
:type => :string,
|
103
|
+
:aliases => "-C",
|
104
|
+
:desc => "Add cache-control headers to S3 objects"
|
105
|
+
|
80
106
|
desc "upload FILES",
|
81
107
|
"Uploads the given files to a S3 bucket as an APT repository."
|
82
108
|
|
@@ -93,12 +119,6 @@ class Deb::S3::CLI < Thor
|
|
93
119
|
"in the repository when uploading one."
|
94
120
|
|
95
121
|
def upload(*files)
|
96
|
-
component = options[:component]
|
97
|
-
if options[:section]
|
98
|
-
component = options[:section]
|
99
|
-
warn("===> WARNING: The --section/-s argument is deprecated, please use --component/-m.")
|
100
|
-
end
|
101
|
-
|
102
122
|
if files.nil? || files.empty?
|
103
123
|
error("You must specify at least one file to upload")
|
104
124
|
end
|
@@ -113,8 +133,13 @@ class Deb::S3::CLI < Thor
|
|
113
133
|
|
114
134
|
# retrieve the existing manifests
|
115
135
|
log("Retrieving existing manifests")
|
116
|
-
release = Deb::S3::Release.retrieve(options[:codename])
|
136
|
+
release = Deb::S3::Release.retrieve(options[:codename], options[:origin], options[:suite], options[:cache_control])
|
117
137
|
manifests = {}
|
138
|
+
release.architectures.each do |arch|
|
139
|
+
manifests[arch] = Deb::S3::Manifest.retrieve(options[:codename], component, arch, options[:cache_control])
|
140
|
+
end
|
141
|
+
|
142
|
+
packages_arch_all = []
|
118
143
|
|
119
144
|
# examine all the files
|
120
145
|
files.collect { |f| Dir.glob(f) }.flatten.each do |file|
|
@@ -126,13 +151,36 @@ class Deb::S3::CLI < Thor
|
|
126
151
|
|
127
152
|
# validate we have them
|
128
153
|
error("No architcture given and unable to determine one for #{file}. " +
|
129
|
-
"Please specify one with --arch [i386
|
154
|
+
"Please specify one with --arch [i386|amd64].") unless arch
|
155
|
+
|
156
|
+
# If the arch is all and the list of existing manifests is none, then
|
157
|
+
# throw an error. This is mainly the case when initializing a brand new
|
158
|
+
# repository. With "all", we won't know which architectures they're using.
|
159
|
+
if arch == "all" && manifests.count == 0
|
160
|
+
error("Package #{File.basename(file)} had architecture \"all\", " +
|
161
|
+
"however noexisting package lists exist. This can often happen " +
|
162
|
+
"if the first package you are add to a new repository is an " +
|
163
|
+
"\"all\" architecture file. Please use --arch [i386|amd64] or " +
|
164
|
+
"another platform type to upload the file.")
|
165
|
+
end
|
130
166
|
|
131
167
|
# retrieve the manifest for the arch if we don't have it already
|
132
|
-
manifests[arch] ||= Deb::S3::Manifest.retrieve(options[:codename], component, arch)
|
168
|
+
manifests[arch] ||= Deb::S3::Manifest.retrieve(options[:codename], component, arch, options[:cache_control])
|
133
169
|
|
134
|
-
# add in
|
170
|
+
# add package in manifests
|
135
171
|
manifests[arch].add(pkg, options[:preserve_versions])
|
172
|
+
|
173
|
+
# If arch is all, we must add this package in all arch available
|
174
|
+
if arch == 'all'
|
175
|
+
packages_arch_all << pkg
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
manifests.each do |arch, manifest|
|
180
|
+
next if arch == 'all'
|
181
|
+
packages_arch_all.each do |pkg|
|
182
|
+
manifest.add(pkg, options[:preserve_versions], false)
|
183
|
+
end
|
136
184
|
end
|
137
185
|
|
138
186
|
# upload the manifest
|
@@ -146,6 +194,158 @@ class Deb::S3::CLI < Thor
|
|
146
194
|
log("Update complete.")
|
147
195
|
end
|
148
196
|
|
197
|
+
desc "list", "Lists packages in given codename, component, and optionally architecture"
|
198
|
+
|
199
|
+
option :long,
|
200
|
+
:type => :boolean,
|
201
|
+
:aliases => '-l',
|
202
|
+
:desc => "Shows all package information in original format",
|
203
|
+
:default => false
|
204
|
+
|
205
|
+
option :arch,
|
206
|
+
:type => :string,
|
207
|
+
:aliases => "-a",
|
208
|
+
:desc => "The architecture of the package in the APT repository."
|
209
|
+
|
210
|
+
def list
|
211
|
+
configure_s3_client
|
212
|
+
|
213
|
+
release = Deb::S3::Release.retrieve(options[:codename])
|
214
|
+
archs = release.architectures
|
215
|
+
archs &= [options[:arch]] if options[:arch] && options[:arch] != "all"
|
216
|
+
widths = [0, 0]
|
217
|
+
rows = archs.map { |arch|
|
218
|
+
manifest = Deb::S3::Manifest.retrieve(options[:codename], component,
|
219
|
+
arch, options[:cache_control])
|
220
|
+
manifest.packages.map do |package|
|
221
|
+
if options[:long]
|
222
|
+
package.generate
|
223
|
+
else
|
224
|
+
[package.name, package.full_version, package.architecture].tap do |row|
|
225
|
+
row.each_with_index do |col, i|
|
226
|
+
widths[i] = [widths[i], col.size].max if widths[i]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
}.flatten(1)
|
232
|
+
|
233
|
+
if options[:long]
|
234
|
+
$stdout.puts rows.join("\n")
|
235
|
+
else
|
236
|
+
rows.each do |row|
|
237
|
+
$stdout.puts "% -#{widths[0]}s % -#{widths[1]}s %s" % row
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
desc "show PACKAGE VERSION ARCH", "Shows information about a package."
|
243
|
+
|
244
|
+
def show(package_name, version, arch)
|
245
|
+
if version.nil?
|
246
|
+
error "You must specify the name of the package to show."
|
247
|
+
end
|
248
|
+
if version.nil?
|
249
|
+
error "You must specify the version of the package to show."
|
250
|
+
end
|
251
|
+
if arch.nil?
|
252
|
+
error "You must specify the architecture of the package to show."
|
253
|
+
end
|
254
|
+
|
255
|
+
configure_s3_client
|
256
|
+
|
257
|
+
# retrieve the existing manifests
|
258
|
+
manifest = Deb::S3::Manifest.retrieve(options[:codename], component, arch,
|
259
|
+
options[:cache_control])
|
260
|
+
package = manifest.packages.detect { |p|
|
261
|
+
p.name == package_name && p.full_version == version
|
262
|
+
}
|
263
|
+
if package.nil?
|
264
|
+
error "No such package found."
|
265
|
+
end
|
266
|
+
|
267
|
+
puts package.generate
|
268
|
+
end
|
269
|
+
|
270
|
+
desc "copy PACKAGE TO_CODENAME TO_COMPONENT ",
|
271
|
+
"Copy the package named PACKAGE to given codename and component. If --versions is not specified, copy all versions of PACKAGE. Otherwise, only the specified versions will be copied. Source codename and component is given by --codename and --component options."
|
272
|
+
|
273
|
+
option :cache_control,
|
274
|
+
:type => :string,
|
275
|
+
:aliases => "-C",
|
276
|
+
:desc => "Add cache-control headers to S3 objects"
|
277
|
+
|
278
|
+
option :arch,
|
279
|
+
:type => :string,
|
280
|
+
:aliases => "-a",
|
281
|
+
:desc => "The architecture of the package in the APT repository."
|
282
|
+
|
283
|
+
option :versions,
|
284
|
+
:default => nil,
|
285
|
+
:type => :array,
|
286
|
+
:desc => "The space-delimited versions of PACKAGE to delete. If not" +
|
287
|
+
"specified, ALL VERSIONS will be deleted. Fair warning." +
|
288
|
+
"E.g. --versions \"0.1 0.2 0.3\""
|
289
|
+
|
290
|
+
option :preserve_versions,
|
291
|
+
:default => false,
|
292
|
+
:type => :boolean,
|
293
|
+
:aliases => "-p",
|
294
|
+
:desc => "Whether to preserve other versions of a package " +
|
295
|
+
"in the repository when uploading one."
|
296
|
+
|
297
|
+
def copy(package_name, to_codename, to_component)
|
298
|
+
if package_name.nil?
|
299
|
+
error "You must specify a package name."
|
300
|
+
end
|
301
|
+
if to_codename.nil?
|
302
|
+
error "You must specify a codename to copy to."
|
303
|
+
end
|
304
|
+
if to_component.nil?
|
305
|
+
error "You must specify a component to copy to."
|
306
|
+
end
|
307
|
+
|
308
|
+
arch = options[:arch]
|
309
|
+
if arch.nil?
|
310
|
+
error "You must specify the architecture of the package to copy."
|
311
|
+
end
|
312
|
+
|
313
|
+
versions = options[:versions]
|
314
|
+
if versions.nil?
|
315
|
+
warn "===> WARNING: Copying all versions of #{package_name}"
|
316
|
+
else
|
317
|
+
log "Versions to copy: #{versions.join(', ')}"
|
318
|
+
end
|
319
|
+
|
320
|
+
configure_s3_client
|
321
|
+
|
322
|
+
# retrieve the existing manifests
|
323
|
+
log "Retrieving existing manifests"
|
324
|
+
from_manifest = Deb::S3::Manifest.retrieve(options[:codename],
|
325
|
+
component, arch,
|
326
|
+
options[:cache_control])
|
327
|
+
to_release = Deb::S3::Release.retrieve(to_codename)
|
328
|
+
to_manifest = Deb::S3::Manifest.retrieve(to_codename, to_component, arch,
|
329
|
+
options[:cache_control])
|
330
|
+
packages = from_manifest.packages.select { |p|
|
331
|
+
p.name == package_name &&
|
332
|
+
(versions.nil? || versions.include?(p.full_version))
|
333
|
+
}
|
334
|
+
if packages.size == 0
|
335
|
+
error "No packages found in repository."
|
336
|
+
end
|
337
|
+
|
338
|
+
packages.each do |package|
|
339
|
+
to_manifest.add package, options[:preserve_versions], false
|
340
|
+
end
|
341
|
+
|
342
|
+
to_manifest.write_to_s3 { |f| sublog("Transferring #{f}") }
|
343
|
+
to_release.update_manifest(to_manifest)
|
344
|
+
to_release.write_to_s3 { |f| sublog("Transferring #{f}") }
|
345
|
+
|
346
|
+
log "Copy complete."
|
347
|
+
end
|
348
|
+
|
149
349
|
desc "delete PACKAGE",
|
150
350
|
"Remove the package named PACKAGE. If --versions is not specified, delete" +
|
151
351
|
"all versions of PACKAGE. Otherwise, only the specified versions will be " +
|
@@ -164,12 +364,6 @@ class Deb::S3::CLI < Thor
|
|
164
364
|
"E.g. --versions \"0.1 0.2 0.3\""
|
165
365
|
|
166
366
|
def delete(package)
|
167
|
-
component = options[:component]
|
168
|
-
if options[:section]
|
169
|
-
component = options[:section]
|
170
|
-
warn("===> WARNING: The --section/-s argument is deprecated, please use --component/-m.")
|
171
|
-
end
|
172
|
-
|
173
367
|
if package.nil?
|
174
368
|
error("You must specify a package name.")
|
175
369
|
end
|
@@ -190,8 +384,8 @@ class Deb::S3::CLI < Thor
|
|
190
384
|
|
191
385
|
# retrieve the existing manifests
|
192
386
|
log("Retrieving existing manifests")
|
193
|
-
release = Deb::S3::Release.retrieve(options[:codename])
|
194
|
-
manifest = Deb::S3::Manifest.retrieve(options[:codename], component, options[:arch])
|
387
|
+
release = Deb::S3::Release.retrieve(options[:codename], options[:origin], options[:suite])
|
388
|
+
manifest = Deb::S3::Manifest.retrieve(options[:codename], component, options[:arch], options[:cache_control])
|
195
389
|
|
196
390
|
deleted = manifest.delete_package(package, versions)
|
197
391
|
if deleted.length == 0
|
@@ -224,20 +418,15 @@ class Deb::S3::CLI < Thor
|
|
224
418
|
:desc => "Whether to fix problems in manifests when verifying."
|
225
419
|
|
226
420
|
def verify
|
227
|
-
component = options[:component]
|
228
|
-
if options[:section]
|
229
|
-
component = options[:section]
|
230
|
-
warn("===> WARNING: The --section/-s argument is deprecated, please use --component/-m.")
|
231
|
-
end
|
232
|
-
|
233
421
|
configure_s3_client
|
234
422
|
|
235
423
|
log("Retrieving existing manifests")
|
236
|
-
release = Deb::S3::Release.retrieve(options[:codename])
|
424
|
+
release = Deb::S3::Release.retrieve(options[:codename], options[:origin], options[:suite])
|
237
425
|
|
238
|
-
|
426
|
+
release.architectures.each do |arch|
|
239
427
|
log("Checking for missing packages in: #{options[:codename]}/#{options[:component]} #{arch}")
|
240
|
-
manifest = Deb::S3::Manifest.retrieve(options[:codename], component,
|
428
|
+
manifest = Deb::S3::Manifest.retrieve(options[:codename], component,
|
429
|
+
arch, options[:cache_control])
|
241
430
|
missing_packages = []
|
242
431
|
|
243
432
|
manifest.packages.each do |p|
|
@@ -250,7 +439,7 @@ class Deb::S3::CLI < Thor
|
|
250
439
|
end
|
251
440
|
end
|
252
441
|
|
253
|
-
if options[:fix_manifests] && !missing_packages.empty?
|
442
|
+
if options[:sign] || (options[:fix_manifests] && !missing_packages.empty?)
|
254
443
|
log("Removing #{missing_packages.length} package(s) from the manifest...")
|
255
444
|
missing_packages.each { |p| manifest.packages.delete(p) }
|
256
445
|
manifest.write_to_s3 { |f| sublog("Transferring #{f}") }
|
@@ -264,16 +453,31 @@ class Deb::S3::CLI < Thor
|
|
264
453
|
|
265
454
|
private
|
266
455
|
|
456
|
+
def component
|
457
|
+
return @component if @component
|
458
|
+
@component = if (section = options[:section])
|
459
|
+
warn("===> WARNING: The --section/-s argument is " \
|
460
|
+
"deprecated, please use --component/-m.")
|
461
|
+
section
|
462
|
+
else
|
463
|
+
options[:component]
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def puts(*args)
|
468
|
+
$stdout.puts(*args) unless options[:quiet]
|
469
|
+
end
|
470
|
+
|
267
471
|
def log(message)
|
268
|
-
puts ">> #{message}"
|
472
|
+
puts ">> #{message}" unless options[:quiet]
|
269
473
|
end
|
270
474
|
|
271
475
|
def sublog(message)
|
272
|
-
puts " -- #{message}"
|
476
|
+
puts " -- #{message}" unless options[:quiet]
|
273
477
|
end
|
274
478
|
|
275
479
|
def error(message)
|
276
|
-
puts "!! #{message}"
|
480
|
+
$stderr.puts "!! #{message}" unless options[:quiet]
|
277
481
|
exit 1
|
278
482
|
end
|
279
483
|
|
@@ -307,6 +511,7 @@ class Deb::S3::CLI < Thor
|
|
307
511
|
Deb::S3::Utils.signing_key = options[:sign]
|
308
512
|
Deb::S3::Utils.gpg_options = options[:gpg_options]
|
309
513
|
Deb::S3::Utils.prefix = options[:prefix]
|
514
|
+
Deb::S3::Utils.encryption = options[:encryption]
|
310
515
|
|
311
516
|
# make sure we have a valid visibility setting
|
312
517
|
Deb::S3::Utils.access_policy =
|
data/lib/deb/s3/manifest.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require "tempfile"
|
2
3
|
require "zlib"
|
3
4
|
require 'deb/s3/utils'
|
@@ -8,21 +9,25 @@ class Deb::S3::Manifest
|
|
8
9
|
|
9
10
|
attr_accessor :codename
|
10
11
|
attr_accessor :component
|
12
|
+
attr_accessor :cache_control
|
11
13
|
attr_accessor :architecture
|
12
14
|
|
13
15
|
attr_accessor :files
|
14
16
|
|
15
17
|
attr_reader :packages
|
18
|
+
attr_reader :packages_to_be_upload
|
16
19
|
|
17
20
|
def initialize
|
18
21
|
@packages = []
|
22
|
+
@packages_to_be_upload = []
|
19
23
|
@component = nil
|
20
24
|
@architecture = nil
|
21
25
|
@files = {}
|
26
|
+
@cache_control = ""
|
22
27
|
end
|
23
28
|
|
24
29
|
class << self
|
25
|
-
def retrieve(codename, component, architecture)
|
30
|
+
def retrieve(codename, component, architecture, cache_control)
|
26
31
|
m = if s = Deb::S3::Utils.s3_read("dists/#{codename}/#{component}/binary-#{architecture}/Packages")
|
27
32
|
self.parse_packages(s)
|
28
33
|
else
|
@@ -32,6 +37,7 @@ class Deb::S3::Manifest
|
|
32
37
|
m.codename = codename
|
33
38
|
m.component = component
|
34
39
|
m.architecture = architecture
|
40
|
+
m.cache_control = cache_control
|
35
41
|
m
|
36
42
|
end
|
37
43
|
|
@@ -45,13 +51,14 @@ class Deb::S3::Manifest
|
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
48
|
-
def add(pkg, preserve_versions)
|
54
|
+
def add(pkg, preserve_versions, needs_uploading=true)
|
49
55
|
if preserve_versions
|
50
56
|
packages.delete_if { |p| p.name == pkg.name && p.full_version == pkg.full_version }
|
51
57
|
else
|
52
58
|
packages.delete_if { |p| p.name == pkg.name }
|
53
59
|
end
|
54
60
|
packages << pkg
|
61
|
+
packages_to_be_upload << pkg if needs_uploading
|
55
62
|
pkg
|
56
63
|
end
|
57
64
|
|
@@ -62,7 +69,7 @@ class Deb::S3::Manifest
|
|
62
69
|
if p.name != pkg
|
63
70
|
p
|
64
71
|
# Also include the packages not matching a specified version
|
65
|
-
elsif (!versions.nil? and p.name == pkg and !versions.include? p.version)
|
72
|
+
elsif (!versions.nil? and p.name == pkg and !versions.include? p.version and !versions.include? p.version + "-" + p.iteration)
|
66
73
|
p
|
67
74
|
end
|
68
75
|
}
|
@@ -79,11 +86,9 @@ class Deb::S3::Manifest
|
|
79
86
|
manifest = self.generate
|
80
87
|
|
81
88
|
# store any packages that need to be stored
|
82
|
-
@
|
83
|
-
|
84
|
-
|
85
|
-
s3_store(pkg.filename, pkg.url_filename, 'application/octet-stream; charset=binary')
|
86
|
-
end
|
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')
|
87
92
|
end
|
88
93
|
|
89
94
|
# generate the Packages file
|
@@ -92,7 +97,7 @@ class Deb::S3::Manifest
|
|
92
97
|
pkgs_temp.close
|
93
98
|
f = "dists/#{@codename}/#{@component}/binary-#{@architecture}/Packages"
|
94
99
|
yield f if block_given?
|
95
|
-
s3_store(pkgs_temp.path, f, '
|
100
|
+
s3_store(pkgs_temp.path, f, 'binary/octet-stream; charset=binary', self.cache_control)
|
96
101
|
@files["#{@component}/binary-#{@architecture}/Packages"] = hashfile(pkgs_temp.path)
|
97
102
|
pkgs_temp.unlink
|
98
103
|
|
@@ -102,7 +107,7 @@ class Deb::S3::Manifest
|
|
102
107
|
Zlib::GzipWriter.open(gztemp.path) { |gz| gz.write manifest }
|
103
108
|
f = "dists/#{@codename}/#{@component}/binary-#{@architecture}/Packages.gz"
|
104
109
|
yield f if block_given?
|
105
|
-
s3_store(gztemp.path, f, 'application/x-gzip; charset=binary')
|
110
|
+
s3_store(gztemp.path, f, 'application/x-gzip; charset=binary', self.cache_control)
|
106
111
|
@files["#{@component}/binary-#{@architecture}/Packages.gz"] = hashfile(gztemp.path)
|
107
112
|
gztemp.unlink
|
108
113
|
|
data/lib/deb/s3/package.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require "digest/sha1"
|
2
3
|
require "digest/sha2"
|
3
4
|
require "digest/md5"
|
4
5
|
require "socket"
|
5
6
|
require "tmpdir"
|
7
|
+
require "uri"
|
8
|
+
|
6
9
|
require 'deb/s3/utils'
|
7
10
|
|
8
11
|
class Deb::S3::Package
|
@@ -21,11 +24,6 @@ class Deb::S3::Package
|
|
21
24
|
attr_accessor :description
|
22
25
|
|
23
26
|
attr_accessor :dependencies
|
24
|
-
attr_accessor :provides
|
25
|
-
attr_accessor :conflicts
|
26
|
-
attr_accessor :replaces
|
27
|
-
attr_accessor :excludes
|
28
|
-
|
29
27
|
|
30
28
|
# Any other attributes specific to this package.
|
31
29
|
# This is where you'd put rpm, deb, or other specific attributes.
|
@@ -116,12 +114,7 @@ class Deb::S3::Package
|
|
116
114
|
@filename = nil
|
117
115
|
@url_filename = nil
|
118
116
|
|
119
|
-
@provides = []
|
120
|
-
@conflicts = []
|
121
|
-
@replaces = []
|
122
117
|
@dependencies = []
|
123
|
-
|
124
|
-
@needs_uploading = false
|
125
118
|
end
|
126
119
|
|
127
120
|
def full_version
|
@@ -131,7 +124,6 @@ class Deb::S3::Package
|
|
131
124
|
|
132
125
|
def filename=(f)
|
133
126
|
@filename = f
|
134
|
-
@needs_uploading = true
|
135
127
|
@filename
|
136
128
|
end
|
137
129
|
|
@@ -143,10 +135,6 @@ class Deb::S3::Package
|
|
143
135
|
@url_filename || "pool/#{self.name[0]}/#{self.name[0..1]}/#{s3_escape(File.basename(self.filename))}"
|
144
136
|
end
|
145
137
|
|
146
|
-
def needs_uploading?
|
147
|
-
@needs_uploading
|
148
|
-
end
|
149
|
-
|
150
138
|
def generate
|
151
139
|
template("package.erb").result(binding)
|
152
140
|
end
|
@@ -232,55 +220,52 @@ class Deb::S3::Package
|
|
232
220
|
|
233
221
|
# from fpm
|
234
222
|
def extract_info(control)
|
235
|
-
|
236
|
-
value = control[/^#{field}: .*/]
|
237
|
-
if value.nil?
|
238
|
-
return nil
|
239
|
-
else
|
240
|
-
return value.split(": ",2).last
|
241
|
-
end
|
242
|
-
end
|
223
|
+
fields = parse_control(control)
|
243
224
|
|
244
225
|
# Parse 'epoch:version-iteration' in the version string
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
raise "Unsupported version string '#{parse.call("Version")}'"
|
226
|
+
full_version = fields.delete('Version')
|
227
|
+
if full_version !~ /^(?:([0-9]+):)?(.+?)(?:-(.*))?$/
|
228
|
+
raise "Unsupported version string '#{full_version}'"
|
249
229
|
end
|
250
|
-
self.epoch, self.version, self.iteration =
|
251
|
-
|
252
|
-
self.architecture =
|
253
|
-
self.category =
|
254
|
-
self.license =
|
255
|
-
self.maintainer =
|
256
|
-
self.name =
|
257
|
-
self.url =
|
258
|
-
self.vendor =
|
259
|
-
self.attributes[:deb_priority] =
|
260
|
-
self.attributes[:deb_origin] =
|
261
|
-
self.attributes[:deb_installed_size] =
|
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')
|
262
242
|
|
263
243
|
# Packages manifest fields
|
264
|
-
|
265
|
-
self.
|
266
|
-
self.
|
267
|
-
self.
|
268
|
-
self.
|
269
|
-
|
270
|
-
|
271
|
-
# The description is the first line as a normal Description field, but also continues
|
272
|
-
# on future lines indented by one space, until the end of the file. Blank
|
273
|
-
# lines are marked as ' .'
|
274
|
-
description = control[/^Description: .*[^\Z]/m]
|
275
|
-
description = description.gsub(/^[^(Description|\s)].*$/, "").split(": ", 2).last
|
276
|
-
self.description = description.gsub(/^ /, "").gsub(/^\.$/, "")
|
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')
|
277
251
|
|
278
252
|
#self.config_files = config_files
|
279
253
|
|
280
|
-
self.dependencies += Array(parse_depends(
|
281
|
-
|
282
|
-
self.
|
283
|
-
self.
|
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
|
+
}]
|
284
269
|
end # def extract_info
|
285
270
|
|
286
271
|
def apply_file_info(file)
|
@@ -289,4 +274,28 @@ class Deb::S3::Package
|
|
289
274
|
self.sha256 = Digest::SHA2.file(file).hexdigest
|
290
275
|
self.md5 = Digest::MD5.file(file).hexdigest
|
291
276
|
end
|
277
|
+
|
278
|
+
def parse_control(control)
|
279
|
+
field = nil
|
280
|
+
value = ""
|
281
|
+
{}.tap do |fields|
|
282
|
+
control.each_line do |line|
|
283
|
+
if line =~ /^(\s+)(\S.*)$/
|
284
|
+
indent, rest = $1, $2
|
285
|
+
# Continuation
|
286
|
+
if indent.size == 1 && rest == "."
|
287
|
+
value << "\n\n"
|
288
|
+
rest = ""
|
289
|
+
elsif value.size > 0
|
290
|
+
value << "\n"
|
291
|
+
end
|
292
|
+
value << rest
|
293
|
+
elsif line =~ /^([-\w]+):(.*)$/
|
294
|
+
fields[field] = value if field
|
295
|
+
field, value = $1, $2.strip
|
296
|
+
end
|
297
|
+
end
|
298
|
+
fields[field] = value if field
|
299
|
+
end
|
300
|
+
end
|
292
301
|
end
|
data/lib/deb/s3/release.rb
CHANGED
@@ -1,32 +1,42 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require "tempfile"
|
2
3
|
|
3
4
|
class Deb::S3::Release
|
4
5
|
include Deb::S3::Utils
|
5
6
|
|
6
7
|
attr_accessor :codename
|
8
|
+
attr_accessor :origin
|
9
|
+
attr_accessor :suite
|
7
10
|
attr_accessor :architectures
|
8
11
|
attr_accessor :components
|
12
|
+
attr_accessor :cache_control
|
9
13
|
|
10
14
|
attr_accessor :files
|
11
15
|
attr_accessor :policy
|
12
16
|
|
13
17
|
def initialize
|
18
|
+
@origin = nil
|
19
|
+
@suite = nil
|
14
20
|
@codename = nil
|
15
21
|
@architectures = []
|
16
22
|
@components = []
|
23
|
+
@cache_control = ""
|
17
24
|
@files = {}
|
18
25
|
@policy = :public_read
|
19
26
|
end
|
20
27
|
|
21
28
|
class << self
|
22
|
-
def retrieve(codename)
|
29
|
+
def retrieve(codename, origin=nil, suite=nil, cache_control=nil)
|
23
30
|
if s = Deb::S3::Utils.s3_read("dists/#{codename}/Release")
|
24
|
-
self.parse_release(s)
|
31
|
+
rel = self.parse_release(s)
|
25
32
|
else
|
26
33
|
rel = self.new
|
27
34
|
rel.codename = codename
|
28
|
-
rel
|
35
|
+
rel.origin = origin unless origin.nil?
|
36
|
+
rel.suite = suite unless suite.nil?
|
29
37
|
end
|
38
|
+
rel.cache_control = cache_control
|
39
|
+
rel
|
30
40
|
end
|
31
41
|
|
32
42
|
def parse_release(str)
|
@@ -52,6 +62,8 @@ class Deb::S3::Release
|
|
52
62
|
|
53
63
|
# grab basic fields
|
54
64
|
self.codename = parse.call("Codename")
|
65
|
+
self.origin = parse.call("Origin") || nil
|
66
|
+
self.suite = parse.call("Suite") || nil
|
55
67
|
self.architectures = (parse.call("Architectures") || "").split(/\s+/)
|
56
68
|
self.components = (parse.call("Components") || "").split(/\s+/)
|
57
69
|
|
@@ -86,7 +98,7 @@ class Deb::S3::Release
|
|
86
98
|
release_tmp.puts self.generate
|
87
99
|
release_tmp.close
|
88
100
|
yield self.filename if block_given?
|
89
|
-
s3_store(release_tmp.path, self.filename, '
|
101
|
+
s3_store(release_tmp.path, self.filename, 'binary/octet-stream; charset=binary', self.cache_control)
|
90
102
|
|
91
103
|
# sign the file, if necessary
|
92
104
|
if Deb::S3::Utils.signing_key
|
@@ -96,7 +108,7 @@ class Deb::S3::Release
|
|
96
108
|
remote_file = self.filename+".gpg"
|
97
109
|
yield remote_file if block_given?
|
98
110
|
raise "Unable to locate Release signature file" unless File.exists?(local_file)
|
99
|
-
s3_store(local_file, remote_file, 'application/pgp-signature; charset=us-ascii')
|
111
|
+
s3_store(local_file, remote_file, 'application/pgp-signature; charset=us-ascii', self.cache_control)
|
100
112
|
File.unlink(local_file)
|
101
113
|
else
|
102
114
|
raise "Signing the Release file failed."
|
@@ -8,25 +8,31 @@ Installed-Size: <%= attributes[:deb_installed_size] %>
|
|
8
8
|
<% if !dependencies.empty? and !attributes[:no_depends?] -%>
|
9
9
|
Depends: <%= dependencies.collect { |d| fix_dependency(d) }.flatten.join(", ") %>
|
10
10
|
<% end -%>
|
11
|
-
<% if
|
12
|
-
Conflicts: <%=
|
11
|
+
<% if attributes[:deb_conflicts] -%>
|
12
|
+
Conflicts: <%= attributes[:deb_conflicts] %>
|
13
|
+
<% end -%>
|
14
|
+
<% if attributes[:deb_breaks] -%>
|
15
|
+
Breaks: <%= attributes[:deb_breaks] %>
|
13
16
|
<% end -%>
|
14
17
|
<% if attributes[:deb_pre_depends] -%>
|
15
|
-
Pre-Depends: <%= attributes[:deb_pre_depends]
|
18
|
+
Pre-Depends: <%= attributes[:deb_pre_depends] %>
|
16
19
|
<% end -%>
|
17
|
-
<% if
|
20
|
+
<% if attributes[:deb_provides] -%>
|
18
21
|
<%# Turn each provides from 'foo = 123' to simply 'foo' because Debian :\ -%>
|
19
22
|
<%# http://www.debian.org/doc/debian-policy/ch-relationships.html -%>
|
20
|
-
Provides: <%=
|
23
|
+
Provides: <%= attributes[:deb_provides] %>
|
21
24
|
<% end -%>
|
22
|
-
<% if
|
23
|
-
Replaces: <%=
|
25
|
+
<% if attributes[:deb_replaces] -%>
|
26
|
+
Replaces: <%= attributes[:deb_replaces] %>
|
24
27
|
<% end -%>
|
25
28
|
<% if attributes[:deb_recommends] -%>
|
26
|
-
Recommends: <%= attributes[:deb_recommends]
|
29
|
+
Recommends: <%= attributes[:deb_recommends] %>
|
27
30
|
<% end -%>
|
28
31
|
<% if attributes[:deb_suggests] -%>
|
29
|
-
Suggests: <%= attributes[:deb_suggests]
|
32
|
+
Suggests: <%= attributes[:deb_suggests] %>
|
33
|
+
<% end -%>
|
34
|
+
<% if attributes[:deb_enhances] -%>
|
35
|
+
Enhances: <%= attributes[:deb_enhances] %>
|
30
36
|
<% end -%>
|
31
37
|
Section: <%= category %>
|
32
38
|
<% if attributes[:deb_origin] -%>
|
@@ -1,7 +1,11 @@
|
|
1
|
+
<% if origin -%>
|
2
|
+
Origin: <%= origin %>
|
3
|
+
<% end -%>
|
1
4
|
Codename: <%= codename %>
|
2
5
|
Date: <%= Time.now.utc.strftime("%a, %d %b %Y %T %Z") %>
|
3
6
|
Architectures: <%= architectures.join(" ") %>
|
4
7
|
Components: <%= components.join(" ") %>
|
8
|
+
Suite: <%= suite %>
|
5
9
|
MD5Sum:
|
6
10
|
<% files.sort.each do |f,p| -%>
|
7
11
|
<%= p[:md5] %> <%= p[:size].to_s.rjust(16) %> <%= f %>
|
data/lib/deb/s3/utils.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require "base64"
|
2
3
|
require "digest/md5"
|
3
4
|
require "erb"
|
@@ -17,6 +18,8 @@ module Deb::S3::Utils
|
|
17
18
|
def gpg_options= v; @gpg_options = v end
|
18
19
|
def prefix; @prefix end
|
19
20
|
def prefix= v; @prefix = v end
|
21
|
+
def encryption; @encryption end
|
22
|
+
def encryption= v; @encryption = v end
|
20
23
|
|
21
24
|
class SafeSystemError < RuntimeError; end
|
22
25
|
|
@@ -46,7 +49,7 @@ module Deb::S3::Utils
|
|
46
49
|
|
47
50
|
# from fog, Fog::AWS.escape
|
48
51
|
def s3_escape(string)
|
49
|
-
string.gsub(/([^a-zA-Z0-9_
|
52
|
+
string.gsub(/([^a-zA-Z0-9_.\-~+]+)/) {
|
50
53
|
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
51
54
|
}
|
52
55
|
end
|
@@ -60,7 +63,7 @@ module Deb::S3::Utils
|
|
60
63
|
Deb::S3::Utils.s3.buckets[Deb::S3::Utils.bucket].objects[s3_path(path)].read
|
61
64
|
end
|
62
65
|
|
63
|
-
def s3_store(path, filename=nil, content_type='application/octet-stream; charset=binary')
|
66
|
+
def s3_store(path, filename=nil, content_type='application/octet-stream; charset=binary', cache_control=nil)
|
64
67
|
filename = File.basename(path) unless filename
|
65
68
|
obj = Deb::S3::Utils.s3.buckets[Deb::S3::Utils.bucket].objects[s3_path(filename)]
|
66
69
|
|
@@ -71,8 +74,16 @@ module Deb::S3::Utils
|
|
71
74
|
return if (file_md5.to_s == obj.etag.gsub('"', '') or file_md5.to_s == obj.metadata['md5'])
|
72
75
|
end
|
73
76
|
|
77
|
+
options = {:acl => Deb::S3::Utils.access_policy, :content_type => content_type, :metadata => {'md5' => file_md5}}
|
78
|
+
if !cache_control.nil?
|
79
|
+
options[:cache_control] = cache_control
|
80
|
+
end
|
81
|
+
|
82
|
+
# specify if encryption is required
|
83
|
+
options[:server_side_encryption] = :aes256 if Deb::S3::Utils.encryption
|
84
|
+
|
74
85
|
# upload the file
|
75
|
-
obj.write(Pathname.new(path),
|
86
|
+
obj.write(Pathname.new(path), options)
|
76
87
|
end
|
77
88
|
|
78
89
|
def s3_remove(path)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deb-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Robertson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -73,16 +73,16 @@ executables:
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
-
- bin/deb-s3
|
77
|
-
- README.md
|
78
76
|
- lib/deb/s3/release.rb
|
77
|
+
- lib/deb/s3/templates/package.erb
|
78
|
+
- lib/deb/s3/templates/release.erb
|
79
79
|
- lib/deb/s3/package.rb
|
80
|
-
- lib/deb/s3/utils.rb
|
81
80
|
- lib/deb/s3/cli.rb
|
82
81
|
- lib/deb/s3/manifest.rb
|
83
|
-
- lib/deb/s3/
|
84
|
-
- lib/deb/s3/templates/package.erb
|
82
|
+
- lib/deb/s3/utils.rb
|
85
83
|
- lib/deb/s3.rb
|
84
|
+
- bin/deb-s3
|
85
|
+
- README.md
|
86
86
|
homepage: http://invalidlogic.com/
|
87
87
|
licenses: []
|
88
88
|
metadata: {}
|