cornelius/inqlude

View on GitHub
lib/rpm_manifestizer.rb

Summary

Maintainability
C
1 day
Test Coverage
# Copyright (C) 2011 Cornelius Schumacher <schumacher@kde.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

class RpmManifestizer

  attr_accessor :dry_run

  def initialize settings
    @settings = settings
  
    @cut_off_exceptions = [ "qt4-x11" ]
    @source_rpms = Hash.new
  end

  def create_manifest name, rpm_name
    qf = 'version:%{VERSION}\n'
    qf += 'summary:%{SUMMARY}\n'
    qf += 'homepage:%{URL}\n'
    qf += 'license:%{LICENSE}\n'
    qf += 'sourcerpm:%{SOURCERPM}\n'
    header = `rpm -q --queryformat '#{qf}' #{rpm_name}`

    header_strings = header.split "\n"
    
    headers = Hash.new
    header_strings.each do |header_string|
      header_string =~ /^(.*?):(.*)$/
      headers[$1] = $2
    end

    source_rpm = headers["sourcerpm"]
    @source_rpms[source_rpm] = Array.new

    raw = `rpm -q --queryformat '%{DESCRIPTION}' #{rpm_name}`
    parse_authors = false
    description = ""
    authors = Array.new
    raw.each_line do |line3|
      if line3 =~ /^Authors:/
        parse_authors = true
        next
      end
      if parse_authors
        if line3 =~ /^---/
          next
        end
        authors.push "\"#{line3.strip}\""
      else
        description += line3.chomp + "\\n"
      end
    end
    description.gsub! /"/, "\\\""
    description.strip!
    
    release_date = Date.parse "1970-01-01"

    licenses = Array.new
    headers["license"].split(";").each do |l|
      licenses.push "\"#{l.strip}\""
    end
    licenses_string = licenses.join ","

    manifest_path = "#{@settings.manifest_path}/#{name}"
    if !File.exists? manifest_path
      Dir.mkdir manifest_path
    end
    filename =  "#{manifest_path}/#{name}.#{release_date}.manifest" 

    File.open( filename, "w") do |f2|      
      f2.puts '{';
      f2.puts '  "schema_version": 1,'
      f2.puts "  \"name\": \"#{name}\","
      f2.puts "  \"release_date\": \"#{release_date}\","
      f2.puts "  \"version\": \"#{headers["version"]}\","
      f2.puts "  \"summary\": \"#{headers["summary"]}\","
      f2.puts '  "urls": {'
      f2.puts "    \"homepage\": \"#{headers["homepage"]}\""
      f2.puts '  },'
      f2.puts "  \"licenses\": [#{licenses_string}],"
      f2.puts "  \"description\": \"#{description}\","
      f2.puts '  "authors": [' + authors.join(",") + '],'
      f2.puts '  "maturity": "stable",'
      f2.puts '  "platforms": [ "Linux" ],'
      f2.puts '  "packages": {'
      f2.puts '    "openSUSE": {'
      f2.puts '      "11.4": {'
      f2.puts "        \"package_name\": \"#{rpm_name}\","
      f2.puts '        "repository": {'
      f2.puts '          "url": "http://download.opensuse.org/distribution/11.4/repo/oss/",'
      f2.puts '          "name": "openSUSE-11.4-Oss"'
      f2.puts '        },'
      f2.puts "        \"source_rpm\": \"#{source_rpm}\""
      f2.puts '      }'
      f2.puts '    }'
      f2.puts '  }'
      f2.puts '}'
    end
  end

  def requires_qt? rpm_name
    IO.popen "rpm -q --requires #{rpm_name}" do |f2|
      while line2 = f2.gets do
        if line2 =~ /Qt/
          return true
        end
      end
    end
    false
  end

  def is_library? rpm_name
    !!(rpm_name =~ /^lib/)
  end

  def is_32bit? rpm_name
    !!(rpm_name =~ /\-32bit/)
  end

  def cut_off_number_suffix name
    if @cut_off_exceptions.include? name
      return name
    end

    i = name.length - 1
    while i > 0
      if name[i].chr !~ /[\-_0-9]/
        break
      end
      i -= 1
    end
    if i > 0
      return name[0..i]
    end
    name
  end

  def process_all_rpms
    if !File.exist? @settings.cache_dir + "/qt_source.json"
      create_qt_source_cache
    end
    
    qt_sources = Hash.new
    File.open @settings.cache_dir + "/qt_source.json" do |file|
      qt_sources = JSON file.read
    end

    qt_sources.each do |source,sections|
      sections["all"].each do |rpm|
        if rpm =~ /(.*)-devel$/
          name = $1

          if name =~ /^lib(.*)/
            name = $1
          end

          lib_rpm = ""
          sections["lib"].each do |lib|
            if lib !~ /\-devel$/
              lib_rpm = lib
              break
            end
          end
          if lib_rpm.empty?
            lib_rpm = rpm
          end
        
          puts "Identified manifest: #{name} (Library RPM: #{lib_rpm})"
        
          if !dry_run
            create_manifest name, lib_rpm
          end
        end
      end
    end
    
    if !dry_run
      patch = @settings.data_path + "/manifest.patch"
      cmd = "cd #{@settings.manifest_path}; patch -p1 <#{patch}";
      puts "Patching manifests with #{patch}"
      system cmd

      patch = @settings.data_path + "/manifest2.patch"
      cmd = "cd #{@settings.manifest_path}; patch -p1 <#{patch}";
      puts "Patching manifests with #{patch}"
      system cmd
    end
  end

  def read_source_cache
    if !File.exist? @settings.cache_dir + "/source.json"
      create_source_cache
    end
  
    sources = Hash.new
    File.open @settings.cache_dir + "/source.json" do |file|
      sources = JSON file.read
    end

    sources
  end

  def create_source_cache
    puts "Creating cache of RPM meta data"
    Upstream.get_involved "Create more friendly progress display for cache creation", 3
    sources = Hash.new
    IO.popen "rpmqpack" do |f|
      while line = f.gets do
        rpm_name = line.chomp
        puts "SCAN #{rpm_name}"
        source_rpm = `rpm -q --queryformat '%{SOURCERPM}' #{rpm_name}`
        sources[rpm_name] = source_rpm
      end
    end

    File.open @settings.cache_dir + "/source.json", "w" do |f|
      f.puts sources.to_json
    end
  end

  def create_qt_source_cache
    puts "Creating cache of Qt library RPMs"

    sources = read_source_cache

    rpms = Hash.new    
    sources.each do |rpm,source|
      if rpms.has_key? source
        rpms[source] = rpms[source].push rpm
      else
        rpms[source] = Array.new.push rpm
      end
    end

    qt_sources = Hash.new
    sources.each do |rpm,source|
      next unless requires_qt? rpm
      next unless is_library? rpm
      next if is_32bit? rpm

      if !qt_sources.has_key? source
        sections = Hash.new
        sections[:all] = Array.new
        sections[:lib] = Array.new
        qt_sources[source] = sections
      end
      
      qt_sources[source][:all] = rpms[source]
      qt_sources[source][:lib] = qt_sources[source][:lib].push rpm

      puts "Found RPM #{rpm} (#{source})"
    end
  
    File.open @settings.cache_dir + "/qt_source.json", "w" do |f|
      f.puts JSON.pretty_generate qt_sources
    end
  end

end