#-- # Webyast Webservice framework # # Copyright (C) 2009, 2010 Novell, Inc. # This library is free software; you can redistribute it and/or modify # it only under the terms of version 2.1 of the GNU Lesser General Public # License as published by the Free Software Foundation. # # This library 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 Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #++ require 'rake' require "tempfile" require "tmpdir" namespace :osc do def obs_project Packaging::Configuration.instance.obs_project end def obs_sr_project Packaging::Configuration.instance.obs_sr_project end def package_name Packaging::Configuration.instance.package_name end def package_dir Packaging::Configuration.instance.package_dir end def build_dist Packaging::Configuration.instance.obs_target end def cleaning rm_rf obs_project puts "cleaning" if verbose end def obs_api Packaging::Configuration.instance.obs_api end def checkout sh "osc -A '#{obs_api}' --traceback --verbose checkout '#{obs_project}' #{package_name}" end def osc_checkout_dir File.join(Dir.pwd, obs_project, package_name) end def copy_sources # clean project to easily add/remove new/old ones Dir["#{osc_checkout_dir}/*"].each do |d| rm d end # copy new Dir["#{package_dir}/*"].each do |f| cp f, osc_checkout_dir end Dir.chdir(osc_checkout_dir) do sh "osc -A '#{obs_api}' addremove" end end def version_changed? updated_spec_file begin file = Tempfile.new('yast-rake') file.close sh "osc -A '#{obs_api}' cat '#{obs_sr_project}' '#{package_name}' '#{package_name}.spec' > #{file.path}" do |ok, res| if !ok puts "Version cannot be compared, so act like it is different" if verbose return true end end original_version = version_from_spec(file.path) new_version = version_from_spec(updated_spec_file) if new_version == original_version puts "Version has not been changed in *.spec file" if verbose return false else puts "Version has been changed in *.spec file" if verbose return true end ensure file.unlink if file end end def version_from_spec spec_glob version = `grep '^Version:' #{spec_glob}` version.sub!(/^Version:\s*/, "") version.sub!(/#.*$/, "") version.strip! version end def different_tarballs?(source1, source2) return true if !File.exist?(source1) || !File.exist?(source2) Dir.mktmpdir("unpacked_tarball") do |d1| sh "tar xvf #{source1} -C #{d1}" Dir.mktmpdir("unpacked_tarball") do |d2| sh "tar xvf #{source2} -C #{d2}" res = `diff -ur #{d1} #{d2}` puts res if verbose return !$?.success? end end end def check_changes! # run spec file service to ensure that just formatting changes is not detected Dir.chdir(package_dir) { sh "/usr/lib/obs/service/format_spec_file --outdir ." } Dir["#{package_dir}/*"].each do |f| orig = f.sub(/#{package_dir}\//, "") if orig =~ /\.(tar|tbz2|tgz|tlz)/ # tar archive, so ignore archive creation time otherwise it always looks like new one return if different_tarballs?(f, File.join(osc_checkout_dir, orig)) else cmd = "diff -u #{f} #{osc_checkout_dir}/#{orig}" puts cmd if verbose puts `bash -c '#{cmd}'` return unless $?.success? # there is something new end end puts "Stop commiting, no difference from devel project" exit 0 end desc "Build package locally" task :build, [:osc_options] => ["check:osc", "package"] do |t, args| args.with_defaults = { :osc_options => "" } raise "Missing information about your Build service project" if !build_dist || !obs_project || !package_name begin checkout copy_sources puts "Building package #{package_name} from project #{obs_project}" if verbose pkg_dir = File.join("/var/tmp", obs_project, build_dist) mkdir_p pkg_dir Dir.chdir osc_checkout_dir do puts "building package..." if verbose # pipe yes to osc build to automatic rebuild broken build root if it happen command = "yes | osc -A '#{obs_api}' build" command << " --no-verify" #ignore untrusted BS projects command << " --release=1" #have always same release number # store packages for given base system at one place, so it speeds up rebuild command << " --keep-pkgs=#{pkg_dir}" command << " #{args[:osc_options]}" command << " #{build_dist}" sh command end ensure cleaning end end MAX_CHANGES_LINES = 20 desc "Commit package to devel project in build service if sources are correct and build" task :commit => "osc:build" do begin checkout # check that there is some changes, otherwise it exit check_changes! copy_sources Dir.chdir osc_checkout_dir do puts "submitting package..." if verbose # Take new lines from changes and use it as commit message. # If a line starts with +, delete + and print it. # Except skip the added "-----" header and the timestamp-author after that, # and skip the +++ diff header changes = `osc -A '#{obs_api}' diff *.changes | sed -n '/^+---/,+2b;/^+++/b;s/^+//;T;p'`.strip if changes.empty? # %h is short hash of a commit git_ref = `git log --format=%h -n 1`.chomp changes = "Updated to git ref #{git_ref}" end # provide only reasonable amount of changes changes = changes.split("\n").take(MAX_CHANGES_LINES).join("\n") sh "osc", "-A", obs_api, "commit", "-m", changes puts "New package submitted to #{obs_project}" if verbose end ensure cleaning end end desc "Create submit request from updated devel project to target project if version change." task :sr => ["check:changelog", "osc:commit"] do begin checkout unless version_changed?( "#{package_dir}/#{package_name}.spec" ) puts "=> no submit request" if verbose else Rake::Task["osc:sr:force"].execute end ensure cleaning end end namespace "sr" do desc "Create submit request from devel project to target project without any other packaging or checking" task :force do # wait for the server service to finish to avoid "service in progress" # error when creating a SR for a freshly commited package puts "Waiting for the server side service..." sh "osc", "-A", obs_api, "service", "wait", obs_project, package_name new_version = version_from_spec("#{package_dir}/#{package_name}.spec") if Packaging::Configuration.instance.maintenance_mode sh "yes | osc -A '#{obs_api}' maintenancerequest --no-cleanup '#{obs_project}' '#{package_name}' '#{obs_sr_project}' -m 'submit new version #{new_version}'" else sh "yes | osc -A '#{obs_api}' submitreq --no-cleanup '#{obs_project}' '#{package_name}' '#{obs_sr_project}' -m 'submit new version #{new_version}' --yes" end end end end