class APTDistsMerge::Merger
Public Class Methods
new(base_dir, incoming_dir, merged_dir)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 5 def initialize(base_dir, incoming_dir, merged_dir) @base_dir = base_dir @incoming_dir = incoming_dir @merged_dir = merged_dir end
Public Instance Methods
merge()
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 11 def merge unless File.exist?(@base_dir) FileUtils.rm_rf(@merged_dir) FileUtils.mkdir_p(@merged_dir) FileUtils.cp_r(Dir.glob("#{@incoming_dir}/*"), @merged_dir) return true end components = (detect_components(@base_dir) | detect_components(@incoming_dir)) components.each do |component| return false unless merge_component(component) end return false unless merge_release true end
Private Instance Methods
binary_release_path(dir, component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 104 def binary_release_path(dir, component, arch) "#{dir}/#{component}/binary-#{arch}/Release" end
contents_path(dir, component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 96 def contents_path(dir, component, arch) "#{dir}/#{component}/Contents-#{arch}" end
debian_version_compare(a, b)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 188 def debian_version_compare(a, b) if system("dpkg", "--compare-versions", a, "eq", b) 0 elsif system("dpkg", "--compare-versions", a, "lt", b) -1 else 1 end end
detect_architectures(dir)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 108 def detect_architectures(dir) data = read_data(release_path(dir)) return [] if data.nil? data.each_line do |line| case line when /\AArchitectures:\s*/ return Regexp.last_match.post_match.split(/\s+/) end end [] end
detect_components(dir)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 120 def detect_components(dir) components = [] Dir.open(dir) do |d| d.each do |path| full_path = "#{dir}/#{path}" next if path.start_with?(".") next unless File.directory?(full_path) components << path end end components end
detect_extensions(base_path)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 29 def detect_extensions(base_path) Dir.glob("#{base_path}*").collect do |path| path.gsub(/\A#{Regexp.escape(base_path)}/, "") end end
generate_checksums(dir, files, digest_class)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 286 def generate_checksums(dir, files, digest_class) checksums = files.collect do |file| checksum = digest_class.file(file).to_s size = File.size(file) relative_path = file.gsub(/\A#{Regexp.escape(dir)}\//, "") " %s %16d %s" % [checksum, size, relative_path] end checksums.join("\n") end
merge_architecture(component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 146 def merge_architecture(component, arch) return false unless merge_contents(component, arch) return false unless merge_packages(component, arch) return false unless merge_binary_release(component, arch) true end
merge_binary_release(component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 234 def merge_binary_release(component, arch) base_path = binary_release_path(@base_dir, component, arch) incoming_path = binary_release_path(@incoming_dir, component, arch) base = read_data(base_path) incoming = read_data(incoming_path) merged = incoming || base merged_path = binary_release_path(@merged_dir, component, arch) write_data(merged, merged_path, detect_extensions(base_path) | detect_extensions(incoming_path)) true end
merge_component(component)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 133 def merge_component(component) architectures = (detect_architectures(@base_dir) | detect_architectures(@incoming_dir)) architectures.each do |arch| return false unless merge_architecture(component, arch) end if File.exist?(source_release_path(@base_dir, component)) or File.exist?(source_release_path(@incoming_dir, component)) return false unless merge_source(component) end true end
merge_contents(component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 153 def merge_contents(component, arch) base_path = contents_path(@base_dir, component, arch) incoming_path = contents_path(@incoming_dir, component, arch) base = read_data(base_path) incoming = read_data(incoming_path) merged = (base.lines | incoming.lines).sort merged_path = contents_path(@merged_dir, component, arch) write_data(merged.join, merged_path, detect_extensions(base_path) | detect_extensions(incoming_path)) true end
merge_packages(component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 220 def merge_packages(component, arch) base_path = packages_path(@base_dir, component, arch) incoming_path = packages_path(@incoming_dir, component, arch) base = read_packages(base_path) incoming = read_packages(incoming_path) merged = merge_packages_data(base, incoming) merged_path = packages_path(@merged_dir, component, arch) write_data(merged.collect {|_, content| "#{content}\n\n"}.join, merged_path, detect_extensions(base_path) | detect_extensions(incoming_path)) true end
merge_packages_data(base, incoming)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 198 def merge_packages_data(base, incoming) packages = (base + incoming).uniq do |metadata,| [metadata["Package"], metadata["Version"]] end packages.sort do |a, b| a_metadata = a[0] b_metadata = b[0] a_package = a_metadata["Package"] b_package = b_metadata["Package"] package_compare = (a_package <=> b_package) if package_compare == 0 debian_version_compare(a_metadata["Version"], b_metadata["Version"]) else if a_package.start_with?(b_package) -1 else package_compare end end end end
merge_release()
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 296 def merge_release base = read_release(release_path(@base_dir)) incoming = read_release(release_path(@incoming_dir)) architectures = base["Architectures"].split | incoming["Architectures"].split components = base["Components"].split | incoming["Components"].split files = Dir.glob("#{@merged_dir}/**/*") files = files.reject do |file| File.directory?(file) end files = files.sort merged = <<-RELEASE Architectures: #{architectures.sort.join(" ")} Codename: #{incoming["Codename"]} Components: #{components.sort.join(" ")} Date: #{incoming["Date"]} Description: #{incoming["Description"]} Label: #{incoming["Label"]} Origin: #{incoming["Origin"]} Suite: #{incoming["Suite"]} MD5Sum: #{generate_checksums(@merged_dir, files, Digest::MD5)} SHA1: #{generate_checksums(@merged_dir, files, Digest::SHA1)} SHA256: #{generate_checksums(@merged_dir, files, Digest::SHA256)} SHA512: #{generate_checksums(@merged_dir, files, Digest::SHA512)} RELEASE merged_path = release_path(@merged_dir) write_data(merged, merged_path) true end
merge_source(component)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 248 def merge_source(component) return false unless merge_sources(component) return false unless merge_source_release(component) true end
merge_source_release(component)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 268 def merge_source_release(component) base_path = source_release_path(@base_dir, component) incoming_path = source_release_path(@incoming_dir, component) base = read_data(base_path) incoming = read_data(incoming_path) merged = incoming || base merged_path = source_release_path(@merged_dir, component) write_data(merged, merged_path, detect_extensions(base_path) | detect_extensions(incoming_path)) true end
merge_sources(component)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 254 def merge_sources(component) base_path = sources_path(@base_dir, component) incoming_path = sources_path(@incoming_dir, component) base = read_packages(base_path) incoming = read_packages(incoming_path) merged = merge_packages_data(base, incoming) merged_path = sources_path(@merged_dir, component) write_data(merged.collect {|_, content| "#{content}\n\n"}.join, merged_path, detect_extensions(base_path) | detect_extensions(incoming_path)) true end
packages_path(dir, component, arch)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 100 def packages_path(dir, component, arch) "#{dir}/#{component}/binary-#{arch}/Packages" end
parse_deb822(content)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 167 def parse_deb822(content) data = {} key = nil content.each_line do |line| case line when /\A / data[key] << "\n" << line else key, value = line.split(/:\s*/, 2) data[key] = value.chomp end end data end
read_data(path)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 35 def read_data(path) if File.exist?(path) File.read(path) elsif File.exist?("#{path}.gz") real_path = "#{path}.gz" Zlib::GzipReader.open(real_path) do |input| input.read end elsif File.exist?("#{path}.xz") real_path = "#{path}.xz" IO.popen(["xz", "--decompress", "--stdout", real_path]) do |input| input.read end else nil end end
read_packages(path)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 182 def read_packages(path) read_data(path).split("\n\n").collect do |content| [parse_deb822(content), content] end end
read_release(path)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 282 def read_release(path) parse_deb822(read_data(path)) end
release_path(dir)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 84 def release_path(dir) "#{dir}/Release" end
source_release_path(dir, component)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 88 def source_release_path(dir, component) "#{dir}/#{component}/source/Release" end
sources_path(dir, component)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 92 def sources_path(dir, component) "#{dir}/#{component}/source/Sources" end
write_data(data, path, extensions=nil)
click to toggle source
# File lib/apt-dists-merge/merger.rb, line 53 def write_data(data, path, extensions=nil) FileUtils.mkdir_p(File.dirname(path)) extensions ||= [""] extensions.each do |extension| case extension when ".gz" Zlib::GzipWriter.open("#{path}#{extension}") do |output| output.write(data) end when ".xz" IO.popen(["xz", "--stdout"], "r+") do |xz| writer = Thread.new do xz.write(data) xz.close_write end File.open("#{path}#{extension}", "wb") do |output| reader = Thread.new do IO.copy_stream(xz, output) end writer.join reader.join end end else File.open(path, "w") do |output| output.write(data) end end end end