Skip to content

Commit 4bf0f32

Browse files
committed
Attempt to atomically update repository metadata
1 parent 0a87272 commit 4bf0f32

File tree

4 files changed

+44
-31
lines changed

4 files changed

+44
-31
lines changed

lib/yum_s3_sync/repo_syncer.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def sync
2020
s3_downloader = YumS3Sync::S3Downloader.new(@target_bucket, @target_base)
2121
dest_repository = YumS3Sync::YumRepository.new(s3_downloader)
2222

23-
s3_uploader = YumS3Sync::S3Uploader.new(@target_bucket, @target_base, http_downloader, @dry_run)
23+
s3_uploader = YumS3Sync::S3Uploader.new(@target_bucket, @target_base, @dry_run)
2424

2525
s3_file_lister = YumS3Sync::S3FileLister.new(@target_bucket, @target_base)
2626
s3_deleter = YumS3Sync::S3Deleter.new(@target_bucket, @target_base, @dry_run)
@@ -33,17 +33,19 @@ def sync
3333
if !dest_repository.metadata[type] || dest_repository.metadata[type][:checksum] != file[:checksum]
3434
new_metadata = true
3535
end
36-
36+
3737
metadata.push file[:href]
3838
end
3939

4040
new_packages.each do |package|
41-
s3_uploader.upload(package, @keep)
41+
if @keep && ! s3_uploader.file_exists?(package)
42+
s3_uploader.upload(package, http_downloader.download(package))
43+
end
4244
end
4345

4446
if !dest_repository.exists? || !new_packages.empty? || new_metadata
45-
metadata.each do |file|
46-
s3_uploader.upload(file, true)
47+
source_repository.metadata.each do |type, file|
48+
s3_uploader.upload(file[:href], file[:file])
4749
end
4850
end
4951

@@ -59,7 +61,7 @@ def sync
5961
puts "Locating missing files"
6062
source_repository.packages.each do |package, data|
6163
unless file_names.include? package
62-
s3_uploader.upload(package, true)
64+
s3_uploader.upload(package, http_downloader.download(package))
6365
end
6466
end
6567

lib/yum_s3_sync/s3_uploader.rb

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,39 @@
22

33
module YumS3Sync
44
class S3Uploader
5-
def initialize(bucket, prefix, downloader, dry_run = false)
5+
def initialize(bucket, prefix, dry_run = false)
66
@bucket = bucket
77
@prefix = prefix
8-
@downloader = downloader
98
@dry_run = dry_run
9+
@s3 = AWS::S3.new
1010
end
1111

12-
def upload(file, overwrite = false)
13-
retries = 0
14-
s3 = AWS::S3.new
15-
16-
begin
17-
target = "#{@prefix}/#{file}"
12+
def file_exists?(source_url)
13+
target = "#{@prefix}/#{source_url}"
1814
target.gsub!(/\/+/, '/')
19-
dest_obj = s3.buckets[@bucket].objects[target]
15+
dest_obj = @s3.buckets[@bucket].objects[target]
2016

21-
if dest_obj.exists? && ! overwrite
22-
puts "Already exists: skipping #{@bucket}::#{target}"
23-
return
17+
if dest_obj.exists?
18+
return true
2419
end
2520

26-
source_file = @downloader.download(file)
21+
return false
22+
end
23+
24+
def upload(source_url, file)
25+
retries = 0
26+
27+
begin
28+
target = "#{@prefix}/#{source_url}"
29+
target.gsub!(/\/+/, '/')
30+
dest_obj = @s3.buckets[@bucket].objects[target]
2731

2832
if @dry_run
2933
puts "Dry-run: Uploading #{@bucket}::#{target}"
3034
else
3135
puts "Uploading #{@bucket}::#{target}"
3236
dest_obj.delete if dest_obj.exists?
33-
dest_obj.write(:file => source_file)
37+
dest_obj.write(:file => file)
3438
end
3539
rescue StandardError => e
3640
if retries < 10

lib/yum_s3_sync/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module YumS3Sync
2-
VERSION = '0.0.13'
2+
VERSION = '0.0.14'
33
end

lib/yum_s3_sync/yum_repository.rb

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env ruby
22

33
require 'zlib'
4+
require 'stringio'
45
require 'nokogiri'
56
require 'rexml/document'
67
require 'rexml/streamlistener'
@@ -15,15 +16,23 @@ def initialize(downloader)
1516

1617
repomd_file = @downloader.download('repodata/repomd.xml')
1718
if repomd_file
18-
doc = Nokogiri::XML(repomd_file)
19+
repomd = StringIO.new(repomd_file.read())
20+
21+
doc = Nokogiri::XML(repomd)
1922
doc.xpath("//xmlns:data").each do |file|
20-
metadata[file['type']] = {
21-
:href => file.xpath('xmlns:location')[0]['href'],
22-
:checksum => file.xpath('xmlns:checksum')[0].child.to_s
23-
}
23+
href = file.xpath('xmlns:location')[0]['href']
24+
f = @downloader.download(href)
25+
if f
26+
metadata[file['type']] = {
27+
:href => href,
28+
:checksum => file.xpath('xmlns:checksum')[0].child.to_s,
29+
:file => StringIO.new(f.read())
30+
}
31+
end
2432
end
2533

26-
@metadata['repomd'] = { :href => 'repodata/repomd.xml' }
34+
repomd.rewind()
35+
@metadata['repomd'] = { :href => 'repodata/repomd.xml', :file => repomd }
2736
else
2837
@metadata = { 'primary' => nil }
2938
end
@@ -32,18 +41,16 @@ def initialize(downloader)
3241
def parse_packages
3342
return {} unless @metadata['primary']
3443

35-
primary_file = @downloader.download(@metadata['primary'][:href])
36-
return {} unless primary_file
37-
3844
puts "Parsing #{@metadata['primary'][:href]}"
39-
gzstream = Zlib::GzipReader.new(primary_file)
45+
gzstream = Zlib::GzipReader.new(@metadata['primary'][:file])
4046

4147
doc = Nokogiri::XML(gzstream)
4248
packages = {}
4349
doc.xpath("//xmlns:package").each do |package|
4450
packages[package.xpath("xmlns:location")[0]['href']] = package.xpath("xmlns:checksum")[0].child.to_s
4551
end
4652

53+
@metadata['primary'][:file].rewind()
4754
packages
4855
end
4956

0 commit comments

Comments
 (0)