File obs_mirror_project of Package obs-server

#!/usr/bin/ruby

# This script mirrors a base distribution from the opensuse.org 
# Build Service. You can use it to create initial base projects
# in your build service to build for.
#
# This script does mirror only build packages, not the sources. 
# Yes, it is just a fast hack for now, please submit cleanups :)
#
# Missing: * switch off building of mirror projects
#            (baserepos are disabled anyway by default)
#          * mirroring of package meta data, needed to build packages
#          * use mirrors by default for downloading

if ARGV.length != 3
  print "Call this script with <project> <repository> <architecture> arguments.\n"
  print "To mirror openSUSE 10.2 as base distro, please call:\n"
  print " \n"
  print "  obs_mirror_project openSUSE:10.2 standard i586 \n"
  print " \n"
  exit(1)
end

project=ARGV[0]
repository=ARGV[1]
architecture=ARGV[2]

rootdir="/srv/obs/" # package default
ownership="obsrun"

projectdir = rootdir + "/projects/" 

destinationdir = rootdir + "build/" + project + "/" + repository + "/" + architecture + "/:full/"
downloadurl = "http://download.opensuse.org/repositories/" + project + "/" + repository 

require 'rexml/document'
include REXML

# prepare project
system("mkdir -p #{destinationdir} #{projectdir}")

# create meta data
system("osc meta prj #{project} > #{projectdir}/#{project}.xml")
system("osc meta prjconf #{project} > #{projectdir}/#{project}.conf")

# download all binary packages
process = File::popen("osc req -m GET https://api.opensuse.org/build/#{project}/#{repository}/#{architecture}/_repository", "r")
filelist = Document.new process
filelist.elements.each("binarylist/binary") { |binary| 
  fname = binary.attributes["filename"];

  # skip src and nosrc rpms
  inform_user_about_hacky_reget=false
  unless fname[-7..-1] == "src.rpm"
    if File.file?("#{destinationdir}/#{fname}")

      puts "package #{destinationdir}/#{fname} already exists."
      inform_user_about_hacky_reget=true

      next

      # TODO: maybe get server side file size or md5 hash or both into
      # _repository, then test if file size matches?  Or maybe even
      # have reget, resuming at file size, then check md5?

      # Checking the integrity of the file, removing it if it's broken
      # to refetch it from the server like this takes aaages, no fun.

      #if system("rpm --checksig #{destinationdir}/#{fname}")
      #  next
      #else
      #  puts "Removing broken download #{destinationdir}/#{fname}"
      #  File.unlink("#{destinationdir}/#{fname}")
      #end

    end
    print "Download " + fname + "\n"
    # FIXME: we can not use the mirrors atm, since the full expanded package name is unknown
    #    unless system("wget -q -N -O #{destinationdir}/#{fname} #{downloadurl}/#{archdir}/#{fname}")
    # fallback to api download
    #      print "failed, try via api for #{fname} \n"
    
    unless system("osc req -m GET https://api.opensuse.org/build/#{project}/#{repository}/#{architecture}/_repository/#{fname} > #{destinationdir}/#{fname}")
      print "Unable to download #{fname} from mirror AND api\n"
      exit(1)
    end
  end

  if inform_user_about_hacky_reget
    puts "\

I skipped the download of packages that already exist.  I did not
check wether those files were correctly or completely downloaded
before.

When you restart the scheduler it will tell you about broken packages
in it's log file in /srv/obs/log/ .  Simply remove the broken package
and re-run this script to update the broken file.

The paranoid may run rpm --checksig, like this:
  rpm --checksig #{destinationdir}/*.rpm

"
  end
}

# fix ownership in case this script did run as root
system("chown -R #{ownership} #{rootdir}/build #{projectdir}")

puts "\
Mirroring succeeded :)
Please restart the scheduler to rescan your projects:

  rcobsscheduler restart"

openSUSE Build Service is sponsored by