pkg-wizard 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.5.2"
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Sergio Rubio
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = pkg-wizard
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to pkg-wizard
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Sergio Rubio. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "pkg-wizard"
16
+ gem.version = File.read 'VERSION'
17
+ gem.homepage = "http://github.com/rubiojr/pkg-wizard"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Package Wizards Tools}
20
+ gem.description = %Q{Tools to manage,create and build distribution packages}
21
+ gem.email = "rubiojr@frameos.org"
22
+ gem.authors = ["Sergio Rubio"]
23
+ gem.add_runtime_dependency 'SystemTimer'
24
+ gem.add_runtime_dependency 'resque'
25
+ gem.add_runtime_dependency 'git'
26
+ gem.add_runtime_dependency 'sinatra'
27
+ gem.add_runtime_dependency 'thin'
28
+ gem.add_runtime_dependency 'rufus-scheduler'
29
+ gem.add_runtime_dependency 'term-ansicolor'
30
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
31
+ end
32
+ Jeweler::RubygemsDotOrgTasks.new
33
+
34
+ require 'rake/rdoctask'
35
+ Rake::RDocTask.new do |rdoc|
36
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+
38
+ rdoc.rdoc_dir = 'rdoc'
39
+ rdoc.title = "pkg-wizard #{version}"
40
+ rdoc.rdoc_files.include('README*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
data/bin/pkgwiz ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pp'
3
+
4
+ $: << File.join(File.dirname(__FILE__), "/../lib/")
5
+
6
+ require 'pkg-wizard'
7
+ require 'pkg-wizard/logger'
8
+ include PKGWizard
9
+
10
+ log = PKGWizard::Logger.instance
11
+
12
+ DEFAULT_SUBCOMMAND_FILES = Dir[File.expand_path(File.join(File.dirname(__FILE__), '/../lib/pkg-wizard/commands/', '*.rb'))]
13
+ DEFAULT_SUBCOMMAND_REGISTRY =
14
+
15
+ DEFAULT_SUBCOMMAND_FILES.each do |sc|
16
+ require sc
17
+ end
18
+
19
+ Command.registry
20
+ #begin
21
+ Command.new.run(ARGV)
22
+ #rescue Exception => e
23
+ # puts "\n#{e.message}\n\n" if not e.is_a?(SystemExit)
24
+ #end
@@ -0,0 +1,42 @@
1
+ module PKGWizard
2
+ class Command
3
+ include ::Mixlib::CLI
4
+
5
+ option :help,
6
+ :short => "-h",
7
+ :long => "--help",
8
+ :description => "Show this message",
9
+ :on => :tail,
10
+ :boolean => true,
11
+ :show_options => true,
12
+ :exit => 0
13
+
14
+ def self.registry
15
+ @@registry ||= []
16
+ end
17
+
18
+ def run(argv)
19
+ @@argv = argv
20
+ cmd = argv.shift
21
+ found = false
22
+ @@registry.each do |c|
23
+ if c[:name] == cmd
24
+ c[:klass].perform
25
+ found = true
26
+ end
27
+ end
28
+ if not found
29
+ puts
30
+ puts "USAGE: #{File.basename($0)} command [options]"
31
+ puts
32
+ puts "Available Commands:"
33
+ puts
34
+ @@registry.each do |c|
35
+ puts c[:name]
36
+ end
37
+ puts
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,108 @@
1
+ require 'pkg-wizard/command'
2
+ require 'pkg-wizard/rpm'
3
+ require 'pkg-wizard/logger'
4
+ require 'pkg-wizard/git'
5
+ require 'pkg-wizard/mock'
6
+ require 'tmpdir'
7
+ require 'fileutils'
8
+ require 'uri'
9
+ require 'sinatra/base'
10
+ require 'rufus/scheduler'
11
+ require 'term/ansicolor'
12
+ require 'pp'
13
+ require 'yaml'
14
+
15
+ class String
16
+ include Term::ANSIColor
17
+ end
18
+
19
+ module PKGWizard
20
+ class BuildBot < Command
21
+
22
+ registry << { :name => 'build-bot', :klass => self }
23
+
24
+ option :help,
25
+ :short => "-h",
26
+ :long => "--help",
27
+ :description => "Show this message",
28
+ :on => :tail,
29
+ :boolean => true,
30
+ :show_options => true,
31
+ :exit => 0
32
+
33
+ option :mock_profile,
34
+ :short => '-m PROF',
35
+ :long => '--mock-profile PROF'
36
+
37
+ class Webapp < Sinatra::Base
38
+ post '/build/' do
39
+ pkg = params[:pkg]
40
+ if pkg.nil?
41
+ Logger.instance.error '400: Invalid arguments. Needs pkg in post request'
42
+ status 400
43
+ "Missing pkg parameter.\n"
44
+ else
45
+ incoming_file = "incoming/#{pkg[:filename]}"
46
+ $stdout.puts "Incoming file".ljust(40).bold.yellow + "#{pkg[:filename]}"
47
+ FileUtils.cp pkg[:tempfile].path, incoming_file
48
+ $stdout.puts "File saved".ljust(40).green.bold + "#{pkg[:filename]}"
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ def self.perform
55
+ cli = BuildBot.new
56
+ cli.banner = "\nUsage: rpmwiz build-bot (options)\n\n"
57
+ cli.parse_options
58
+ mock_profile = cli.config[:mock_profile]
59
+ if not mock_profile
60
+ $stderr.puts 'Invalid mock profile.'
61
+ $stderr.puts cli.opt_parser.help
62
+ exit
63
+ end
64
+ meta = { :mock_profile => mock_profile }
65
+
66
+ Dir.mkdir 'incoming' if not File.exist?('incoming')
67
+ Dir.mkdir 'output' if not File.exist?('output')
68
+ Dir.mkdir 'workspace' if not File.exist?('workspace')
69
+ scheduler = Rufus::Scheduler.start_new
70
+ scheduler.every '2s', :blocking => true do
71
+ meta[:start_time] = Time.now
72
+ queue = Dir['incoming/*.src.rpm'].sort_by {|filename| File.mtime(filename) }
73
+ if not queue.empty?
74
+ job_time = Time.now.strftime '%Y%m%d_%H%M%S'
75
+ $stdout.puts "Job accepted [#{queue.size} Queued]".ljust(40).blue.bold + job_time
76
+ job_dir = "workspace/job_#{Time.now.strftime '%Y%m%d_%H%M%S'}"
77
+ result_dir = job_dir + '/result'
78
+ FileUtils.mkdir_p result_dir
79
+ meta[:source] = File.basename(queue.first)
80
+ qfile = File.join(job_dir, File.basename(queue.first))
81
+ FileUtils.mv queue.first, qfile
82
+ $stdout.puts "Building pkg [#{job_time}]".ljust(40).yellow.bold + "#{File.basename(qfile)}"
83
+
84
+ begin
85
+ PKGWizard::Mock.srpm :srpm => qfile, :profile => mock_profile, :resultdir => result_dir
86
+ meta[:status] = 'ok'
87
+ $stdout.puts "Finished building [#{job_time}]".ljust(40).green.bold + "#{File.basename(qfile)}"
88
+ rescue Exception => e
89
+ meta[:status] = 'error'
90
+ $stdout.puts "Job failed [#{job_time}]".ljust(40).red.bold
91
+ File.open(job_dir + '/buildbot.log', 'w') do |f|
92
+ f.puts "#{e.backtrace.join("\n")}"
93
+ f.puts "#{e.message}"
94
+ end
95
+ ensure
96
+ meta[:endtime] = Time.now
97
+ File.open(job_dir + '/meta.yml', 'w') do |f|
98
+ f.puts meta.to_yaml
99
+ end
100
+ FileUtils.mv job_dir, 'output/'
101
+ end
102
+ end
103
+ end
104
+ Webapp.run!
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,89 @@
1
+ require 'pkg-wizard/command'
2
+ require 'pkg-wizard/rpm'
3
+ require 'pkg-wizard/logger'
4
+ require 'pkg-wizard/git'
5
+ require 'tmpdir'
6
+ require 'fileutils'
7
+ require 'uri'
8
+
9
+ module PKGWizard
10
+ class CreateSrpm < Command
11
+ registry << { :name => 'create-srpm', :klass => self }
12
+
13
+ option :help,
14
+ :short => "-h",
15
+ :long => "--help",
16
+ :description => "Show this message",
17
+ :on => :tail,
18
+ :boolean => true,
19
+ :show_options => true,
20
+ :exit => 0
21
+
22
+ option :gitrepo,
23
+ :short => '-g REPO',
24
+ :long => '--gitrepo REPO',
25
+ :description => 'Git repo URL to fetch the package sources from'
26
+
27
+ option :workspace,
28
+ :short => '-w DIR',
29
+ :long => '--workspace DIR',
30
+ :description => 'Git repo URL to fetch the package sources from'
31
+
32
+ option :resultdir,
33
+ :short => '-r DIR',
34
+ :long => '--resultdir DIR',
35
+ :description => 'Path for resulting files to be put'
36
+
37
+ def self.perform
38
+ cmd = CreateSrpm.new
39
+ cmd.banner = "\nUsage: rpmwiz create-srpm (options)\n\n"
40
+ cmd.parse_options
41
+ repo = cmd.config[:gitrepo]
42
+ workspace = cmd.config[:workspace] || "/tmp/rpmwiz-#{Time.now.to_i}"
43
+ FileUtils.mkdir_p(workspace) if not File.exist?(workspace)
44
+ source_dir = workspace + '/SOURCES'
45
+
46
+ resultdir = cmd.config[:resultdir] || workspace + '/SRPMS'
47
+ if not File.exist?(resultdir)
48
+ Dir.mkdir(resultdir)
49
+ end
50
+
51
+ if not File.exist?(resultdir)
52
+ raise Exception.new("resultdir #{resultdir} does not exist.")
53
+ end
54
+ if repo
55
+ begin
56
+ repo_name = URI.parse(repo).path.split('/').last.gsub(/\.git$/,'')
57
+ rescue Exception => e
58
+ raise Exception.new('Invalid Git repo URL')
59
+ end
60
+ repo_dir = File.join(source_dir, repo_name)
61
+ if not File.exist?(repo_dir)
62
+ FileUtils.mkdir_p repo_dir
63
+ end
64
+ GitRPM.fetch(repo, repo_dir)
65
+ pwd = Dir.pwd
66
+ Dir.chdir repo_dir
67
+ output = SRPM.create
68
+ # FIXME
69
+ # This is dangerous but SRPM.create does not return
70
+ # the full filename
71
+ pkg = output
72
+ basename = File.basename(pkg)
73
+ Dir.chdir pwd
74
+ FileUtils.cp pkg, resultdir
75
+ $stdout.puts "SRPM created: #{resultdir}/#{basename}"
76
+ else
77
+ output = SRPM.create
78
+ # FIXME
79
+ # This is dangerous but SRPM.create does not return
80
+ # the full filename
81
+ pkg = output
82
+ basename = File.basename(pkg)
83
+ FileUtils.cp pkg, resultdir
84
+ $stdout.puts "SRPM created: #{resultdir}/#{basename}"
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,113 @@
1
+ require 'pkg-wizard/command'
2
+ require 'pkg-wizard/logger'
3
+ require 'pkg-wizard/streaming_downloader'
4
+ require 'tmpdir'
5
+ require 'fileutils'
6
+ require 'uri'
7
+ require 'term/ansicolor'
8
+ require 'pkg-wizard/streaming_uploader'
9
+ require 'pp'
10
+
11
+ class String
12
+ include Term::ANSIColor
13
+ end
14
+
15
+ module PKGWizard
16
+ class RemoteBuild < Command
17
+
18
+ registry << { :name => 'remote-build', :klass => self }
19
+
20
+ option :help,
21
+ :short => "-h",
22
+ :long => "--help",
23
+ :description => "Show this message",
24
+ :on => :tail,
25
+ :boolean => true,
26
+ :show_options => true,
27
+ :exit => 0
28
+
29
+ option :buildbot,
30
+ :short => '-b URL',
31
+ :description => 'rpmwiz build-bot URL',
32
+ :long => '--buildbot URL'
33
+
34
+ option :tmpdir,
35
+ :short => '-t TEMP',
36
+ :long => '--tmpdir TEMP',
37
+ :description => 'Directory for downloaded files to be put',
38
+ :default => '/tmp'
39
+
40
+ def self.perform
41
+ cli = RemoteBuild.new
42
+ cli.banner = "\nUsage: rpmwiz remote-build (options)\n\n"
43
+ pkgs = cli.parse_options
44
+ bbot_url = cli.config[:buildbot]
45
+ if bbot_url.nil?
46
+ $stderr.puts "\n--buildbot is required.\n"
47
+ puts cli.opt_parser.help
48
+ exit 1
49
+ end
50
+ downloaded_pkgs = []
51
+ pkgs.reject! do |p|
52
+ if p =~ /http:\/\//
53
+ pkg = URI.parse(p).path.split("/").last
54
+ $stdout.puts "Downloading #{pkg}..."
55
+ downloaded_pkgs << download_from_url(p,cli.config[:tmpdir])
56
+ true
57
+ else
58
+ false
59
+ end
60
+ end
61
+ pkgs += downloaded_pkgs
62
+
63
+ #
64
+ # If no packages are specified, we assume we need to create
65
+ # and SRPM from current dir
66
+ #
67
+ created_srpms = []
68
+ if pkgs.empty? and Dir["*.spec"].size > 0
69
+ spec = Dir["*.spec"].first
70
+ $stdout.puts "Creating SRPM for #{spec}..."
71
+ srpm = SRPM.create
72
+ created_srpms << srpm
73
+ end
74
+ pkgs += created_srpms
75
+
76
+ # We need this to show the progress percentage
77
+ if pkgs.empty?
78
+ $stderr.puts "\nNo packages found.\n\n"
79
+ puts cli.opt_parser.help
80
+ exit 1
81
+ end
82
+ pkgs.each do |pkg|
83
+ fo = File.new(pkg)
84
+ fsize = File.size(pkg)
85
+ count = 0
86
+ $stdout.sync = true
87
+ line_reset = "\r\e[0K"
88
+ res = StreamingUploader.post(
89
+ bbot_url + '/build/',
90
+ { 'pkg' => fo }
91
+ ) do |size|
92
+ count += size
93
+ per = (100*count)/fsize
94
+ if per %10 == 0
95
+ print "#{line_reset}Uploading:".ljust(40) + "#{(100*count)/fsize}% "
96
+ end
97
+ end
98
+ #puts "#{line_reset}Uploading: #{File.basename(pkg).gsub(/-((\d|\.)*)-(.*)\.src\.rpm/,'')} ".ljust(40) + "#{(100*count)/fsize}% [COMPLETE]"
99
+ puts "#{line_reset}Uploading: #{File.basename(pkg)} ".ljust(40) + "#{(100*count)/fsize}% [COMPLETE]"
100
+ end
101
+ end
102
+
103
+ def self.download_from_url(url, tmpdir = '/tmp')
104
+ uri = URI.parse(url)
105
+ remote_pkg = uri.path.split('/').last
106
+ d = StreamingDownloader.new
107
+ f = "#{tmpdir}/#{remote_pkg}"
108
+ d.download!(url, File.new(f, 'w'))
109
+ f
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,17 @@
1
+ require 'git'
2
+
3
+ module PKGWizard
4
+
5
+ class GitRPM
6
+ def self.fetch(giturl, path)
7
+ # We pull if clone exists
8
+ if File.directory?(path + '/.git')
9
+ c = Git.open(path)
10
+ c.pull
11
+ else
12
+ Git.clone giturl, path
13
+ end
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'logger'
2
+ require 'delegate'
3
+ require 'singleton'
4
+
5
+ module PKGWizard
6
+ OriginalLogger = Logger
7
+ class Logger < SimpleDelegator
8
+ include Singleton
9
+
10
+ def initialize
11
+ @logger = OriginalLogger.new(STDOUT)
12
+ super @logger
13
+ end
14
+ end
15
+
16
+ def set_output(log_device)
17
+ @logger = OriginalLogger.new(log_device)
18
+ __setobj__(@logger)
19
+ end
20
+
21
+ end
@@ -0,0 +1,45 @@
1
+ module PKGWizard
2
+ class Mock
3
+
4
+ #
5
+ # mandatory args
6
+ # :profile
7
+ # :resultdir
8
+ # :srpm
9
+ #
10
+ def self.srpm(args = {})
11
+ mock_profile = args[:profile]
12
+ result_dir = args[:resultdir]
13
+ srpm = args[:srpm]
14
+ mock_args = args[:mock_args] || ""
15
+
16
+ raise ArgumentError.new('Invalid mock profile') if mock_profile.nil?
17
+
18
+ if not File.exist?(srpm) or (srpm !~ /src\.rpm$/)
19
+ raise ArgumentError.new('Invalid SRPM')
20
+ end
21
+
22
+ raise ArgumentError.new('Invalid result dir') if result_dir.nil?
23
+
24
+
25
+ if mock_profile.nil?
26
+ raise Exception.new "Missing mock profile."
27
+ end
28
+
29
+ if result_dir.nil?
30
+ raise Exception.new "Missing result_dir."
31
+ end
32
+
33
+ if not File.directory?(result_dir)
34
+ raise Exception.new "Invalid result_dir #{result_dir}"
35
+ end
36
+
37
+ cmd = "/usr/bin/mock #{mock_args} -r #{mock_profile} --disable-plugin ccache --resultdir #{result_dir} #{srpm}"
38
+ output = `#{cmd} 2>&1`
39
+ if $? != 0
40
+ raise Exception.new(output)
41
+ end
42
+ output
43
+ end
44
+ end # class
45
+ end # mod
@@ -0,0 +1,63 @@
1
+ module PKGWizard
2
+ class NoSpecFound < Exception; end
3
+ class RPMBuildError < Exception; end
4
+
5
+ class RPM
6
+ end
7
+
8
+ class SpecFile
9
+ attr_accessor :name, :release, :version
10
+
11
+ def self.parse(file)
12
+ f = File.read(file)
13
+ spec = SpecFile.new
14
+ spec.name = f.match(/Name:(.*?)$/)[1].strip.chomp
15
+ spec.version = f.match(/Version:(.*?)$/)[1].strip.chomp
16
+ spec.release = f.match(/Release:(.*?)$/)[1].strip.chomp.gsub(/%\{\?.*\}/, '')
17
+ spec
18
+ end
19
+
20
+ def pkgname
21
+ "#{name}-#{version}-#{release}"
22
+ end
23
+
24
+ end
25
+
26
+ class SRPM
27
+ #
28
+ # params
29
+ # rpmbuild_dir: _topdir macro
30
+ # macros: macros string
31
+ #
32
+ def self.create(params = {})
33
+ rpmbuild_dir = params[:rpmbuild_dir] || "#{ENV['HOME']}/rpmbuild/"
34
+ macros = params[:macros] || ''
35
+ rhel5_compat = params[:rhel5_compat] || false
36
+ specs = Dir["*.spec"]
37
+ raise NoSpecFound.new 'No spec found in current dir' if specs.empty?
38
+ pkg_name = File.read(specs.first).match(/Name:(.*?)$/)[1].strip.chomp
39
+ pkg_ver = File.read(specs.first).match(/Version:(.*?)$/)[1].strip.chomp
40
+ pkg_release = File.read(specs.first).match(/Release:(.*?)$/)[1].strip.chomp.gsub(/%\{\?.*\}/, '')
41
+ pkg_full_name = "#{pkg_name}-#{pkg_ver}-#{pkg_release}"
42
+ %w(SOURCES SRPMS SPECS BUILDROOT RPMS BUILD).each do |d|
43
+ Dir.mkdir File.join(File.expand_path(rpmbuild_dir), d) if not File.exist?(File.join(rpmbuild_dir, d))
44
+ end
45
+ Dir['*'].each do |f|
46
+ FileUtils.cp(f, "#{rpmbuild_dir}/SOURCES") if not File.directory?(f)
47
+ end
48
+ macros << " --define '_topdir #{rpmbuild_dir}'"
49
+ if rhel5_compat
50
+ macros << ' --define "_source_filedigest_algorithm 0" --define "_binary_filedigest_algorithm 0"'
51
+ end
52
+ output = `rpmbuild --nodeps -bs *.spec #{macros} 2>&1`
53
+ resulting_pkg = ''
54
+ output.each_line do |l|
55
+ if l =~ /Wrote:/
56
+ resulting_pkg = l.gsub('Wrote: ', '').strip.chomp
57
+ end
58
+ end
59
+ raise RPMBuildError.new(output) if $? != 0
60
+ resulting_pkg
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,62 @@
1
+ module PKGWizard
2
+
3
+ #
4
+ # StreamingDownloader code based on HTTPDownloader
5
+ # code from http://www.vagrantup.com
6
+ #
7
+ class StreamingDownloader
8
+ def self.match?(uri)
9
+ # URI.parse barfs on '<drive letter>:\\files \on\ windows'
10
+ extracted = URI.extract(uri).first
11
+ extracted && extracted.include?(uri)
12
+ end
13
+
14
+ def report_progress(progress, total, show_parts=true)
15
+ line_reset = "\r\e[0K"
16
+ percent = (progress.to_f / total.to_f) * 100
17
+ line = "Progress: #{percent.to_i}%"
18
+ line << " (#{progress} / #{total})" if show_parts
19
+ line = "#{line_reset}#{line}"
20
+ $stdout.sync = true
21
+ $stdout.print line
22
+ end
23
+
24
+ def download!(source_url, destination_file)
25
+ proxy_uri = URI.parse(ENV["http_proxy"] || "")
26
+ uri = URI.parse(source_url)
27
+ http = Net::HTTP.new(uri.host, uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
28
+
29
+ if uri.scheme == "https"
30
+ http.use_ssl = true
31
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
+ end
33
+
34
+ http.start do |h|
35
+ h.request_get(uri.request_uri) do |response|
36
+ total = response.content_length
37
+ progress = 0
38
+ segment_count = 0
39
+
40
+ response.read_body do |segment|
41
+ # Report the progress out
42
+ progress += segment.length
43
+ segment_count += 1
44
+
45
+ # Progress reporting is limited to every 25 segments just so
46
+ # we're not constantly updating
47
+ if segment_count % 25 == 0
48
+ report_progress(progress, total)
49
+ segment_count = 0
50
+ end
51
+
52
+
53
+ # Store the segment
54
+ destination_file.write(segment)
55
+ end
56
+ end
57
+ end
58
+ rescue SocketError
59
+ raise Errors::DownloaderHTTPSocketError.new
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,145 @@
1
+ # StreamingUploader Adapted by Sergio Rubio <srubio@abiquo.com> for Abiquo
2
+ #
3
+ # inspired by Opscode Chef StreamingCookbookUploader chef/streaming_cookbook_uploader.rb
4
+ # http://opscode.com
5
+ #
6
+ # inspired by/cargo-culted from http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
7
+ # On Apr 6, 2010, at 3:00 PM, Stanislav Vitvitskiy wrote:
8
+ #
9
+ # It's free to use / modify / distribute. No need to mention anything. Just copy/paste and use.
10
+ #
11
+ # Regards,
12
+ # Stan
13
+
14
+ require 'net/http'
15
+
16
+ module PKGWizard
17
+
18
+ class StreamingUploader
19
+
20
+ class << self
21
+
22
+ def post(to_url, params = {}, &block)
23
+ boundary = '----RubyMultipartClient' + rand(1000000).to_s + 'ZZZZZ'
24
+ parts = []
25
+ content_file = nil
26
+
27
+ unless params.nil? || params.empty?
28
+ params.each do |key, value|
29
+ if value.kind_of?(File)
30
+ content_file = value
31
+ filepath = value.path
32
+ filename = File.basename(filepath)
33
+ parts << StringPart.new( "--" + boundary + "\r\n" +
34
+ "Content-Disposition: form-data; name=\"" + key.to_s + "\"; filename=\"" + filename + "\"\r\n" +
35
+ "Content-Type: application/octet-stream\r\n\r\n")
36
+ parts << StreamPart.new(value, File.size(filepath))
37
+ parts << StringPart.new("\r\n")
38
+ else
39
+ parts << StringPart.new( "--" + boundary + "\r\n" +
40
+ "Content-Disposition: form-data; name=\"" + key.to_s + "\"\r\n\r\n")
41
+ parts << StringPart.new(value.to_s + "\r\n")
42
+ end
43
+ end
44
+ parts << StringPart.new("--" + boundary + "--\r\n")
45
+ end
46
+
47
+ body_stream = MultipartStream.new(parts, block)
48
+
49
+ url = URI.parse(to_url)
50
+
51
+ headers = { 'accept' => 'application/json' }
52
+
53
+ req = Net::HTTP::Post.new(url.path)
54
+ req.content_length = body_stream.size
55
+ req.content_type = 'multipart/form-data; boundary=' + boundary unless parts.empty?
56
+ req.body_stream = body_stream
57
+
58
+ http = Net::HTTP.new(url.host, url.port)
59
+ res = http.request(req)
60
+ #res = http.start {|http_proc| http_proc.request(req) }
61
+
62
+ res
63
+ end
64
+
65
+ end
66
+
67
+ class StreamPart
68
+ def initialize(stream, size)
69
+ @stream, @size = stream, size
70
+ end
71
+
72
+ def size
73
+ @size
74
+ end
75
+
76
+ # read the specified amount from the stream
77
+ def read(offset, how_much)
78
+ @stream.read(how_much)
79
+ end
80
+ end
81
+
82
+ class StringPart
83
+ def initialize(str)
84
+ @str = str
85
+ end
86
+
87
+ def size
88
+ @str.length
89
+ end
90
+
91
+ # read the specified amount from the string startiung at the offset
92
+ def read(offset, how_much)
93
+ @str[offset, how_much]
94
+ end
95
+ end
96
+
97
+ class MultipartStream
98
+ def initialize(parts, blk = nil)
99
+ @callback = nil
100
+ if blk
101
+ @callback = blk
102
+ end
103
+ @parts = parts
104
+ @part_no = 0
105
+ @part_offset = 0
106
+ end
107
+
108
+ def size
109
+ @parts.inject(0) {|size, part| size + part.size}
110
+ end
111
+
112
+ def read(how_much)
113
+ @callback.call(how_much) if @callback
114
+ return nil if @part_no >= @parts.size
115
+
116
+ how_much_current_part = @parts[@part_no].size - @part_offset
117
+
118
+ how_much_current_part = if how_much_current_part > how_much
119
+ how_much
120
+ else
121
+ how_much_current_part
122
+ end
123
+
124
+ how_much_next_part = how_much - how_much_current_part
125
+
126
+ current_part = @parts[@part_no].read(@part_offset, how_much_current_part)
127
+
128
+ # recurse into the next part if the current one was not large enough
129
+ if how_much_next_part > 0
130
+ @part_no += 1
131
+ @part_offset = 0
132
+ next_part = read(how_much_next_part)
133
+ current_part + if next_part
134
+ next_part
135
+ else
136
+ ''
137
+ end
138
+ else
139
+ @part_offset += how_much_current_part
140
+ current_part
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
data/lib/pkg-wizard.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'mixlib/cli'
4
+
5
+ module PKGWizard
6
+
7
+ class Distribution
8
+ def self.detect
9
+ if File.exist?('/etc/redhat-release') and \
10
+ File.read('/etc/redhat-release') =~ /Fedora/
11
+ return Fedora.new
12
+ end
13
+ if File.exist?('/etc/redhat-release') and \
14
+ File.read('/etc/redhat-release') =~ /FrameOS|RedHat|CentOS/
15
+ return RedHat.new
16
+ end
17
+ if `lsb_release -i` =~ /Ubuntu/
18
+ return Ubuntu.new
19
+ end
20
+ return UnknownDistro.new
21
+ end
22
+ end
23
+
24
+ class UnknownDistro
25
+ def prepare_env
26
+ end
27
+
28
+ def to_s
29
+ 'unknown'
30
+ end
31
+ end
32
+
33
+ class Ubuntu
34
+ def prepare_env
35
+ end
36
+ def to_s
37
+ 'ubuntu'
38
+ end
39
+ end
40
+
41
+ class RedHat
42
+ def prepare_env
43
+ if `uname -r` =~ /\.el6\./
44
+ else
45
+ raise UnsupportedDistribution.new('Unsupported RHEL distribution')
46
+ end
47
+ output = `yum install createrepo yum-utils rsync git rpmdevtools wget mock 2>&1`
48
+ end
49
+ def to_s
50
+ 'redhat'
51
+ end
52
+ end
53
+
54
+ class Fedora
55
+ def prepare_env
56
+ end
57
+ def to_s
58
+ 'fedora'
59
+ end
60
+ end
61
+
62
+ class UnsupportedDistribution < Exception
63
+ end
64
+
65
+ end
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pkg-wizard
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ version: 0.1.2
11
+ platform: ruby
12
+ authors:
13
+ - Sergio Rubio
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-14 00:00:00 +01:00
19
+ default_executable: pkgwiz
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ hash: 23
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 0
32
+ version: 1.0.0
33
+ name: bundler
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 7
44
+ segments:
45
+ - 1
46
+ - 5
47
+ - 2
48
+ version: 1.5.2
49
+ name: jeweler
50
+ prerelease: false
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ name: SystemTimer
64
+ prerelease: false
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ name: resque
78
+ prerelease: false
79
+ type: :runtime
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ name: git
92
+ prerelease: false
93
+ type: :runtime
94
+ version_requirements: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ name: sinatra
106
+ prerelease: false
107
+ type: :runtime
108
+ version_requirements: *id006
109
+ - !ruby/object:Gem::Dependency
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ name: thin
120
+ prerelease: false
121
+ type: :runtime
122
+ version_requirements: *id007
123
+ - !ruby/object:Gem::Dependency
124
+ requirement: &id008 !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ name: rufus-scheduler
134
+ prerelease: false
135
+ type: :runtime
136
+ version_requirements: *id008
137
+ - !ruby/object:Gem::Dependency
138
+ requirement: &id009 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ name: term-ansicolor
148
+ prerelease: false
149
+ type: :runtime
150
+ version_requirements: *id009
151
+ description: Tools to manage,create and build distribution packages
152
+ email: rubiojr@frameos.org
153
+ executables:
154
+ - pkgwiz
155
+ extensions: []
156
+
157
+ extra_rdoc_files:
158
+ - LICENSE.txt
159
+ - README.rdoc
160
+ files:
161
+ - .document
162
+ - Gemfile
163
+ - LICENSE.txt
164
+ - README.rdoc
165
+ - Rakefile
166
+ - VERSION
167
+ - bin/pkgwiz
168
+ - lib/pkg-wizard.rb
169
+ - lib/pkg-wizard/command.rb
170
+ - lib/pkg-wizard/commands/build_bot.rb
171
+ - lib/pkg-wizard/commands/create_srpm.rb
172
+ - lib/pkg-wizard/commands/remote_build.rb
173
+ - lib/pkg-wizard/git.rb
174
+ - lib/pkg-wizard/logger.rb
175
+ - lib/pkg-wizard/mock.rb
176
+ - lib/pkg-wizard/rpm.rb
177
+ - lib/pkg-wizard/streaming_downloader.rb
178
+ - lib/pkg-wizard/streaming_uploader.rb
179
+ - packages/epel-release-5-4.noarch.rpm
180
+ - packages/epel-release-6-5.noarch.rpm
181
+ has_rdoc: true
182
+ homepage: http://github.com/rubiojr/pkg-wizard
183
+ licenses:
184
+ - MIT
185
+ post_install_message:
186
+ rdoc_options: []
187
+
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ none: false
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ hash: 3
196
+ segments:
197
+ - 0
198
+ version: "0"
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ hash: 3
205
+ segments:
206
+ - 0
207
+ version: "0"
208
+ requirements: []
209
+
210
+ rubyforge_project:
211
+ rubygems_version: 1.3.7
212
+ signing_key:
213
+ specification_version: 3
214
+ summary: Package Wizards Tools
215
+ test_files: []
216
+