From: Jinkun Jang Date: Tue, 12 Mar 2013 17:19:52 +0000 (+0900) Subject: Tizen 2.1 base X-Git-Tag: 2.1b_release~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8c18b506154dd9a281194b3542079254f25003b3;p=sdk%2Ftools%2Fsdk-build.git Tizen 2.1 base --- diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE index 4297ee3..901a81c 100644 --- a/NOTICE +++ b/NOTICE @@ -1 +1,3 @@ -Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. +Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License terms and conditions. diff --git a/README b/README index e54ec3f..f373da2 100644 --- a/README +++ b/README @@ -142,7 +142,7 @@ Building a SDK package is very simple. Here is the command for buiding package. ## pkg-build [-u ] [-o ] [-c ] [-r ] ## -u : Package server URL which contains binary and development packages. ## If ommited, it will use previous server URL. - ## -o : Target OS(linux or windows) + ## -o : Target OS(ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64) ## -c : Clean build"" ## If set, start build after downloading all dependent packages ## If not set, it will not download dependent packages if already downloaded @@ -195,7 +195,7 @@ There are more useful commands provided You can list up available packages of server. ## pkg-cli list-rpkg [-o ] [-u ] - ## -o : Target OS(linux or windows) + ## -o : Target OS(ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64) ## -u : Package server URL which contains binary and development packages. ## If ommited, it will use previous server URL. diff --git a/build-cli b/build-cli index 425c32a..fb9758e 100755 --- a/build-cli +++ b/build-cli @@ -1,7 +1,7 @@ -#!/usr/bin/ruby -d +#!/usr/bin/ruby =begin - + build-cli Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -35,75 +35,295 @@ $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/build_server" require "utils" require "BuildClientOptionParser" require "BuildComm" +require "FileTransferViaFTP" +require "FileTransferViaDirect" + -#option parsing -option = option_parse - -# if "--os" is not specified, use host os type -if option[:os].nil? then - option[:os] = Utils::HOST_OS -else - if not option[:os] =~ /^(linux|windows|darwin)$/ then - puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS " - exit 1 - end +#option parsing +begin + option = option_parse +rescue => e + puts e.message + exit 0 end -if option[:domain].nil? then - option[:domain] = "172.21.17.46" + +# check HOST OS +if not Utils.check_host_OS() then + puts "Error: Your host OS is not supported!" + exit 1 +end + +def query( ip, port, sym ) + client = BuildCommClient.create( ip, port, nil, 0 ) + if client.nil? then + puts "Connection to server failed!" + return nil + end + client.send "QUERY|#{sym.strip}" + result = client.receive_data() + if result.nil? then + puts "Error: #{client.get_error_msg()}" + end + client.terminate + return result +end + +def query_system_info(ip, port) + # HOST SYSTEM INFO + puts "* SYSTEM INFO *" + data = query( ip, port, "SYSTEM") + if data.nil? then exit 1 end + + result = data[0].split(",").map { |x| x.strip } + puts "HOST-OS: #{result[0]}" + puts "MAX_WORKING_JOBS: #{result[1]}" + + # FTP INFO + puts "\n* FTP *" + data = query(ip, port, "FTP") + if data.nil? then exit 1 end + + result = data[0].split(",").map { |x| x.strip } + puts "FTP_ADDR: #{result[0]}" + puts "FTP_USERNAME: #{result[1]}" + + # SUPPORTED OS INFO + puts "\n* SUPPORTED OS LIST *" + data = query(ip, port, "OS") + if data.nil? then exit 1 end + + data.each do |item| + puts "#{item.strip}" + end + + # Friend lists + puts "\n* FRIEND SERVER LIST (WAIT|WORK/MAX) jobs [transfer count] *" + data = query(ip, port, "FRIEND") + if data.nil? then exit 1 end + i = 0 + data.each do |item| + i = i + 1 + info = item.split(",").map { |x| x.strip } + if info[0] == "DISCONNECTED" then + puts "#{i}. #{info[0]}" + else + puts "#{i}. #{info[0]} #{info[1]} server (#{info[2]}|#{info[3]}/#{info[4]}) [#{info[5]}]" + end + end end -if option[:port].nil? then - option[:port] = 2222 + +def query_project_list(ip, port) + puts "* PROJECT(S) *" + data = query( ip, port, "PROJECT") + data.each do |item| + tok = item.split(",").map { |x| x.strip } + type = (tok[0]=="G" ? "NORMAL":"REMOTE") + printf("%-25s %s %s\n",tok[1],type,tok[2]) + end +end + + +def query_job_list(ip, port) + puts "* JOB(S) *" + data = query(ip, port, "JOB") + data.each do |item| + tok = item.split(",").map { |x| x.strip } + if tok[4].nil? then + puts "#{tok[1]} #{tok[0]} #{tok[2]} #{tok[3]}" + else + puts "#{tok[1]} #{tok[0]} #{tok[2]} (#{tok[3]}) #{tok[4]}" + end + end +end + + +# if "--os" is not specified, use pe +if option[:os].nil? then + option[:os] = "default" +end + +if option[:domain].nil? then + puts "Warn: Build server IP address is not specified. 127.0.0.1 will be used" + option[:domain] = "127.0.0.1" end begin - case option[:cmd] - when "build" - client = BuildCommClient.create( option[:domain], option[:port]) + case option[:cmd] + when "build" + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + client = BuildCommClient.create( result[0], result[1], nil, 0 ) if not client.nil? then - client.send "BUILD,GIT,#{option[:git]},#{option[:commit]},#{option[:os]},,#{option[:async]}" - client.print_stream + client.send "BUILD|GIT|#{option[:project]}|#{option[:passwd]}|#{option[:os]}|#{option[:async]}|#{option[:noreverse]}|#{option[:dist]}|#{option[:user]}|#{option[:verbose]}" + if not client.print_stream then + puts "ERROR: #{client.get_error_msg()}" + end + client.terminate + else + puts "Connection to server failed!" + exit 1 end when "resolve" - client = BuildCommClient.create( option[:domain], option[:port]) - if not client.nil? then - client.send "RESOLVE,GIT,#{option[:git]},#{option[:commit]},#{option[:os]},,#{option[:async]}" - client.print_stream - client.terminate + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 end - when "query" - # SYSTEM INFO - client = BuildCommClient.create( option[:domain], option[:port]) + client = BuildCommClient.create( result[0], result[1], nil, 0 ) if not client.nil? then - client.send "QUERY,SYSTEM" - result0 = client.receive_data() - if result0.nil? then - client.terminate - exit(-1) + client.send "RESOLVE|GIT|#{option[:project]}|#{option[:passwd]}|#{option[:os]}|#{option[:async]}|#{option[:dist]}|#{option[:user]}|#{option[:verbose]}" + if not client.print_stream then + puts "ERROR: #{client.get_error_msg()}" end - result0 = result0[0].split(",").map { |x| x.strip } - puts "HOST-OS: #{result0[0]}" - puts "MAX_WORKING_JOBS: #{result0[1]}" client.terminate end + when "query" + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end - # JOB INFO - client = BuildCommClient.create( option[:domain], option[:port]) - if not client.nil? then - client.send "QUERY,JOB" - result1 = client.receive_data() - if result0.nil? then - client.terminate - exit(-1) + query_system_info( result[0], result[1] ) + puts "" + query_project_list( result[0], result[1]) + puts "" + query_job_list( result[0], result[1]) + + when "query-system" + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + + query_system_info( result[0], result[1] ) + + when "query-project" + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + + query_project_list( result[0], result[1]) + + when "query-job" + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + + query_job_list( result[0], result[1] ) + + when "cancel" + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + if not option[:job].nil? then + client = BuildCommClient.create( result[0], result[1], nil, 0 ) + if not client.nil? then + client.send "CANCEL|#{option[:job]}|#{option[:passwd]}|#{option[:user]}" + result1 = client.receive_data() + if result1.nil? then + puts "Error: #{client.get_error_msg()}" + client.terminate + exit 1 + end + puts result1 + else + puts "Connection to server failed!" + exit 1 end - puts "* JOB *" - for item in result1 - tok = item.split(",").map { |x| x.strip } - puts "#{tok[1]} #{tok[0]} #{tok[2]}" + else + puts "you must input \"cancel job number\"!!" + exit 1 + end + + when "register" + # check file exist + if not File.exist? option[:package] then + puts "The file does not exist!.. #{option[:package]}" + exit(-1) + end + + result = Utils.parse_server_addr(option[:domain]) + if result.nil? then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + bs_ip = result[0] + bs_port = result[1] + + if not option[:fdomain].nil? then + ftp_result = Utils.parse_ftpserver_url(option[:fdomain]) + if ftp_result.nil? or ftp_result.length != 4 then + puts "FTP server url is incorrect. (#{option[:fdomain]})" + puts "Tune as following format." + puts " ftp://:@
" + exit 1 end + ip = ftp_result[0] + port = ftp_result[1] + username = ftp_result[2] + passwd = ftp_result[3] + transporter = FileTransferFTP.new( nil, ip, port, username, passwd ) + else + transporter = FileTransferDirect.new( nil ) + end + + # upload + client = BuildCommClient.create( bs_ip, bs_port, nil, 0 ) + if client.nil? then + puts "Can't access server #{bs_ip}:#{bs_port}" + exit(-1) + end + dock = Utils.create_uniq_name() + msg = "UPLOAD|#{dock}" + client.send( msg ) + result = client.send_file(option[:package], transporter) + client.terminate + if not result then + puts "Uploading file failed!.. #{option[:package]}" + exit(-1) + end + + # register + client = BuildCommClient.create( bs_ip, bs_port, nil, 0 ) + if client.nil? then + puts "Can't access server #{bs_ip}:#{bs_port}" + exit(-1) + end + client.send("REGISTER|BINARY|#{File.basename(option[:package])}|#{option[:passwd]}|#{dock}|#{option[:dist]}|#{option[:user]}|#{option[:noreverse]}") + if not client.print_stream then + puts "ERROR: #{client.get_error_msg()}" end + client.terminate else raise RuntimeError, "input option incorrect : #{option[:cmd]}" diff --git a/build-svr b/build-svr index f1ddaf9..fc9a98f 100755 --- a/build-svr +++ b/build-svr @@ -1,7 +1,7 @@ -#!/usr/bin/ruby -d +#!/usr/bin/ruby =begin - + build-svr Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -32,70 +32,191 @@ require 'fileutils' $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common" $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/build_server" require "utils" +require "log.rb" require "BuildServerOptionParser" require "BuildServerController" -#option parsing +#option parsing begin option = option_parse rescue => e - puts "Option parse error" puts e.message exit 0 end - -# if "--os" is not specified, use host os type -if option[:os].nil? then - host_os = `uname -s`.strip - case host_os - when "Linux" - option[:os] = "linux" - when /MINGW32.*/ - option[:os] = "windows" - when "Darwin" - option[:os] = "darwin" - else - if not option[:os] =~ /^(linux|windows|darwin)$/ then - puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS " - exit 1 - end - end -else - if not option[:os] =~ /^(linux|windows|darwin)$/ then - puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS " - exit 1 - end -end - - +# check HOST OS +if not Utils.check_host_OS() then + puts "Error: Your host OS is not supported!" + exit 1 +end begin - case option[:cmd] - when "create" - BuildServerController.create_server( option[:name], Utils::WORKING_DIR, option[:url], option[:domain], option[:pid] ) + case option[:cmd] + when "create" + ftpsvr_addr = nil; ftpsvr_port = nil; ftpsvr_username = nil; ftpsvr_passwd = nil + if not option[:fdomain].nil? then + ftp_result = Utils.parse_ftpserver_url(option[:fdomain]) + if ftp_result.nil? or ftp_result.length != 4 then + puts "FTP server url is incorrect. (#{option[:fdomain]})" + puts "Tune as following format." + puts " ftp://:@
:" + exit 1 + end + ftpsvr_addr = ftp_result[0] + ftpsvr_port = ftp_result[1] + ftpsvr_username = ftp_result[2] + ftpsvr_passwd = ftp_result[3] + end + BuildServerController.create_server( option[:name], Utils::WORKING_DIR, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd ) when "remove" - BuildServerController.remove_server( option[:name] ) + BuildServerController.remove_server( option[:name] ) + when "migrate" + BuildServerController.migrate_server( option[:name], option[:db_dsn], option[:db_user], option[:db_passwd] ) when "start" - BuildServerController.start_server( option[:name], option[:port] ) - when "build" - if not option[:git].nil? then - if option[:resolve] then - BuildServerController.resolve_git( option[:name], option[:git], option[:commit], option[:os], nil ) - else - BuildServerController.build_git( option[:name], option[:git], option[:commit], option[:os], nil ) + if( option[:child] ) then # Child Process + BuildServerController.start_server( option[:name], option[:port] ) + else # Parent Process + # check server config + if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/server.cfg" + raise RuntimeError, "The server \"#{option[:name]}\" does not exist!" + end + + log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/main.log" ) + begin + while(true) + log.info "Build Server[#{option[:name]}] Start - PORT:[#{option[:port]}]" + # Start child process + cmd = Utils.generate_shell_command("#{File.dirname(__FILE__)}/build-svr start -n #{option[:name]} -p #{option[:port]} --CHILD") + IO.popen(cmd) + pid = Process.wait + + # End chlid process + log.info "Child process terminated, pid = #{pid}, status = #{$?.exitstatus}" + if ($?.exitstatus == 0) then # SERVER STOP COMMAND + log.info "Down Build Server." + break + elsif ($?.exitstatus == 99) then # DIBS UPGRADE + cmd = "#{File.dirname(__FILE__)}/upgrade -l #{File.dirname(__FILE__)} -S -t BUILDSERVER -n #{option[:name]} -p #{option[:port]}" + if File.exist? "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist" then + File.open("#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist","r") do |f| + f.each_line do |l| + cmd += " -D #{l.strip}" + break + end + end + File.delete "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist" + end + + cmd = Utils.generate_shell_command(cmd) + puts cmd + Utils.spawn(cmd) + log.info cmd + log.info "Down Build Server for DIBS upgrade." + break + else + log.error "Down Build Server. Try reboot Build Server." + end + end + rescue => e + log.error( e.message, Log::LV_USER) end - elsif not option[:local].nil? then - if option[:resolve] then - BuildServerController.resolve_local( option[:name], option[:local], option[:os], nil ) + end + when "stop" + BuildServerController.stop_server( option[:name] ) + + when "upgrade" + if not (option[:dist].nil? or option[:dist].empty?) then + build_server = BuildServerController.get_server(option[:name]) + # distribution check + if not build_server.distmgr.get_distribution(option[:dist]).nil? then + File.open("#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist","w") do |f| + f.puts option[:dist] + end else - BuildServerController.build_local( option[:name], option[:local], option[:os], nil ) + puts "Distribution \"#{option[:dist]}\" is not exits" + puts "Upgrade Failed!!" + exit 1 end + end + + BuildServerController.upgrade_server( option[:name] ) + + when "add-svr" + svr_result = Utils.parse_server_addr(option[:domain]) + if svr_result.nil? or svr_result.length != 2 then + puts "Server address is incorrect. Tune as following format." + puts " :" + exit 1 + end + pkgsvr_addr = svr_result[0] + pkgsvr_port = svr_result[1] + BuildServerController.add_remote_server( option[:name], pkgsvr_addr, pkgsvr_port ) + + when "remove-svr" + BuildServerController.remove_remote_server( option[:name], pkgsvr_addr, pkgsvr_port ) + + when "add-os" + BuildServerController.add_target_os( option[:name], option[:os] ) + + when "remove-os" + BuildServerController.remove_target_os( option[:name], option[:os] ) + + when "add-dist" + svr_result = Utils.parse_server_addr(option[:domain]) + if svr_result.nil? or svr_result.length != 2 then + puts "Server address is incorrect. (#{option[:domain]})" + puts "Tune as following format." + puts " :" + exit 1 + end + pkgsvr_url = option[:url] + pkgsvr_addr = svr_result[0] + pkgsvr_port = svr_result[1] + BuildServerController.add_distribution( option[:name], option[:dist], pkgsvr_url, pkgsvr_addr, pkgsvr_port ) + + when "remove-dist" + BuildServerController.remove_distribution( option[:name], option[:dist] ) + + when "lock-dist" + BuildServerController.lock_distribution( option[:name], option[:dist] ) + + when "unlock-dist" + BuildServerController.unlock_distribution( option[:name], option[:dist] ) + + when "add-sync" + BuildServerController.add_sync_package_server( option[:name], option[:url], option[:dist] ) + + when "remove-sync" + BuildServerController.remove_sync_package_server( option[:name], option[:url], option[:dist] ) + + when "add-prj" + if not option[:git].nil? then + BuildServerController.add_project( option[:name], option[:pid], + option[:git], option[:branch], option[:remote], option[:passwd], + option[:os], option[:dist] ) else - RuntimeError "Wrong build options are specified!" + BuildServerController.add_binary_project( option[:name], option[:pid], + option[:package], option[:passwd], option[:os], option[:dist] ) end - when "add" - BuildServerController.add_friend_server( option[:name], option[:domain], option[:port] ) + + when "remove-prj" + BuildServerController.remove_project( option[:name], option[:pid], option[:dist] ) + + when "fullbuild" + BuildServerController.build_all_projects( option[:name], option[:dist] ) + + when "register" + BuildServerController.register_package( option[:name], option[:package], option[:dist] ) + + when "query" + BuildServerController.query_server( option[:name] ) + + when "set-attr" + BuildServerController.set_server_attribute( option[:name], option[:attr], option[:value] ) + + when "get-attr" + BuildServerController.get_server_attribute( option[:name], option[:attr] ) + else raise RuntimeError, "input option incorrect : #{option[:cmd]}" end diff --git a/dibs-web/Gemfile b/dibs-web/Gemfile new file mode 100644 index 0000000..cfe9b05 --- /dev/null +++ b/dibs-web/Gemfile @@ -0,0 +1,50 @@ +source 'https://rubygems.org' + +gem 'rails', '3.2.8' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3' + +gem 'json' + +gem 'execjs' + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', '~> 3.2.3' + gem 'coffee-rails', '~> 3.2.1' + + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + # gem 'therubyracer', :platforms => :ruby + + gem 'uglifier', '>= 1.0.3' +end + +gem 'jquery-rails' + +# mysql +gem 'mysql2', '> 0.3' # as stated above + +# user +gem 'builder' + +# For encrypt password +gem "bcrypt-ruby", :require => "bcrypt" + +# To use ActiveModel has_secure_password +# gem 'bcrypt-ruby', '~> 3.0.0' + +# To use Jbuilder templates for JSON +# gem 'jbuilder' + +# Use unicorn as the app server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug' diff --git a/dibs-web/Gemfile.lock b/dibs-web/Gemfile.lock new file mode 100644 index 0000000..d4f7f1a --- /dev/null +++ b/dibs-web/Gemfile.lock @@ -0,0 +1,118 @@ +GEM + remote: https://rubygems.org/ + specs: + actionmailer (3.2.8) + actionpack (= 3.2.8) + mail (~> 2.4.4) + actionpack (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.4) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.3) + activemodel (3.2.8) + activesupport (= 3.2.8) + builder (~> 3.0.0) + activerecord (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activeresource (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) + activesupport (3.2.8) + i18n (~> 0.6) + multi_json (~> 1.0) + arel (3.0.2) + bcrypt-ruby (3.0.1) + builder (3.0.3) + coffee-rails (3.2.2) + coffee-script (>= 2.2.0) + railties (~> 3.2.0) + coffee-script (2.2.0) + coffee-script-source + execjs + coffee-script-source (1.3.3) + erubis (2.7.0) + execjs (1.4.0) + multi_json (~> 1.0) + hike (1.2.1) + i18n (0.6.1) + journey (1.0.4) + jquery-rails (2.1.3) + railties (>= 3.1.0, < 5.0) + thor (~> 0.14) + json (1.7.5) + mail (2.4.4) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.19) + multi_json (1.3.6) + mysql2 (0.3.11) + polyglot (0.3.3) + rack (1.4.1) + rack-cache (1.2) + rack (>= 0.4) + rack-ssl (1.3.2) + rack + rack-test (0.6.2) + rack (>= 1.0) + rails (3.2.8) + actionmailer (= 3.2.8) + actionpack (= 3.2.8) + activerecord (= 3.2.8) + activeresource (= 3.2.8) + activesupport (= 3.2.8) + bundler (~> 1.0) + railties (= 3.2.8) + railties (3.2.8) + actionpack (= 3.2.8) + activesupport (= 3.2.8) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (>= 0.14.6, < 2.0) + rake (0.9.2.2) + rdoc (3.12) + json (~> 1.4) + sass (3.2.1) + sass-rails (3.2.5) + railties (~> 3.2.0) + sass (>= 3.1.10) + tilt (~> 1.3) + sprockets (2.1.3) + hike (~> 1.2) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + sqlite3 (1.3.6) + thor (0.16.0) + tilt (1.3.3) + treetop (1.4.10) + polyglot + polyglot (>= 0.3.1) + tzinfo (0.3.33) + uglifier (1.3.0) + execjs (>= 0.3.0) + multi_json (~> 1.0, >= 1.0.2) + +PLATFORMS + ruby + +DEPENDENCIES + bcrypt-ruby + builder + coffee-rails (~> 3.2.1) + execjs + jquery-rails + json + mysql2 (> 0.3) + rails (= 3.2.8) + sass-rails (~> 3.2.3) + sqlite3 + uglifier (>= 1.0.3) diff --git a/dibs-web/README.rdoc b/dibs-web/README.rdoc new file mode 100644 index 0000000..7c36f23 --- /dev/null +++ b/dibs-web/README.rdoc @@ -0,0 +1,261 @@ +== Welcome to Rails + +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. + +This pattern splits the view (also called the presentation) into "dumb" +templates that are primarily responsible for inserting pre-built data in between +HTML tags. The model contains the "smart" domain objects (such as Account, +Product, Person, Post) that holds all the business logic and knows how to +persist themselves to a database. The controller handles the incoming requests +(such as Save New Account, Update Product, Show Post) by manipulating the model +and directing data to the view. + +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. + +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. + + +== Getting Started + +1. At the command prompt, create a new Rails application: + rails new myapp (where myapp is the application name) + +2. Change directory to myapp and start the web server: + cd myapp; rails server (run with --help for options) + +3. Go to http://localhost:3000/ and you'll see: + "Welcome aboard: You're riding Ruby on Rails!" + +4. Follow the guidelines to start developing your application. You can find +the following resources handy: + +* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html +* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands +running on the server.log and development.log. Rails will automatically display +debugging and runtime information to these files. Debugging info will also be +shown in the browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code +using the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are +several books available online as well: + +* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two books will bring you up to speed on the Ruby language and also on +programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your +Mongrel or WEBrick server with --debugger. This means that you can break out of +execution at any point in the code, investigate and change the model, and then, +resume execution! You need to install ruby-debug to run the server in debugging +mode. With gems, use sudo gem install ruby-debug. Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.all + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, "body"=>nil, "id"=>"1"}>, + #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better, you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you can enter "cont". + + +== Console + +The console is a Ruby shell, which allows you to interact with your +application's domain model. Here you'll have all parts of the application +configured, just like it is when the application is running. You can inspect +domain models, change values, and save to the database. Starting the script +without arguments will launch it in the development environment. + +To start the console, run rails console from the application +directory. + +Options: + +* Passing the -s, --sandbox argument will rollback any modifications + made to the database. +* Passing an environment name as an argument will load the corresponding + environment. Example: rails console production. + +To reload your controllers and models after launching the console run +reload! + +More information about irb can be found at: +link:http://www.rubycentral.org/pickaxe/irb.html + + +== dbconsole + +You can go to the command line of your database directly through rails +dbconsole. You would be connected to the database with the credentials +defined in database.yml. Starting the script without arguments will connect you +to the development database. Passing an argument will connect you to a different +database, like rails dbconsole production. Currently works for MySQL, +PostgreSQL and SQLite 3. + +== Description of Contents + +The default directory structure of a generated Ruby on Rails application: + + |-- app + | |-- assets + | |-- images + | |-- javascripts + | `-- stylesheets + | |-- controllers + | |-- helpers + | |-- mailers + | |-- models + | `-- views + | `-- layouts + |-- config + | |-- environments + | |-- initializers + | `-- locales + |-- db + |-- doc + |-- lib + | `-- tasks + |-- log + |-- public + |-- script + |-- test + | |-- fixtures + | |-- functional + | |-- integration + | |-- performance + | `-- unit + |-- tmp + | |-- cache + | |-- pids + | |-- sessions + | `-- sockets + `-- vendor + |-- assets + `-- stylesheets + `-- plugins + +app + Holds all the code that's specific to this particular application. + +app/assets + Contains subdirectories for images, stylesheets, and JavaScript files. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from + ApplicationController which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. Models descend from + ActiveRecord::Base by default. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use + eRuby syntax by default. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the + common header/footer method of wrapping views. In your views, define a layout + using the layout :default and create a file named default.html.erb. + Inside default.html.erb, call <% yield %> to render the view using this + layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are + generated for you automatically when using generators for controllers. + Helpers can be used to wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, + and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all the + sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when + generated using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that + doesn't belong under controllers, models, or helpers. This directory is in + the load path. + +public + The directory available for the web server. Also contains the dispatchers and the + default HTML files. This should be set as the DOCUMENT_ROOT of your web + server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate + command, template test files will be generated for you and placed in this + directory. + +vendor + External libraries that the application depends on. Also includes the plugins + subdirectory. If the app has frozen rails, those gems also go here, under + vendor/rails/. This directory is in the load path. diff --git a/dibs-web/Rakefile b/dibs-web/Rakefile new file mode 100644 index 0000000..f818fd1 --- /dev/null +++ b/dibs-web/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Dibs::Application.load_tasks diff --git a/dibs-web/app/assets/images/rails.png b/dibs-web/app/assets/images/rails.png new file mode 100644 index 0000000..d5edc04 Binary files /dev/null and b/dibs-web/app/assets/images/rails.png differ diff --git a/dibs-web/app/controllers/admin_controller.rb b/dibs-web/app/controllers/admin_controller.rb new file mode 100644 index 0000000..b2803d5 --- /dev/null +++ b/dibs-web/app/controllers/admin_controller.rb @@ -0,0 +1,79 @@ +=begin + admin_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class AdminController < ApplicationController + + before_filter :check_login_status, :check_admin_group + + def queryAllOS + os_list = SupportedOs.all(:order => "name") + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + if not os_list.nil? + os_list.each do |os| + doc.OS { + doc.OsName(os.name) + category = OsCategory.find(:first, :conditions => ["id = ?", os.os_category_id]) + if not category.nil? + doc.OsCategory(category.name) + end + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def queryAllOSCategory + os_category_list = OsCategory.all(:order => "name") + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + if not os_category_list.nil? + os_category_list.each do |category| + doc.OsCategoryName(category.name) + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + +end diff --git a/dibs-web/app/controllers/admin_distribution_controller.rb b/dibs-web/app/controllers/admin_distribution_controller.rb new file mode 100644 index 0000000..6d838c6 --- /dev/null +++ b/dibs-web/app/controllers/admin_distribution_controller.rb @@ -0,0 +1,261 @@ +=begin + admin_distribution_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class AdminDistributionController < ApplicationController + + before_filter :check_login_status, :check_admin_group + + def queryAllDistribution + # get full distribution list + distributions = Distribution.all + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + #generate to XML + doc.Data { + if not distributions.nil? + distributions.each do |distribution| + doc.DistributionName(distribution.name) + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def queryDistributionInfo + dist_name = params[:distribution] + + if dist_name.nil? or dist_name.empty? + render :text => "Distribution name is empty", :content_type => "text/xml", :status => 406 + return + end + + # get distribution + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + if distribution.nil? + render :text => "Can't find distribution : #{dist_name}", :content_type => "text/xml", :status => 406 + return + end + + # get sync package server + sync_package_server = SyncPkgServer.find(:first, :conditions => ["distribution_id = ?", distribution.id]) + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + #generate to XML + doc.Data{ + doc.DistributionInfo{ + doc.DistributionName(distribution.name) + doc.PackageServerUrl(distribution.pkgsvr_url) + doc.PackageServerAddress(distribution.pkgsvr_addr) + doc.Status(distribution.status) + doc.Description(distribution.description) + } + + doc.SyncPackageServer{ + if sync_package_server.nil? + doc.Url("") + doc.Period("") + doc.Description("") + else + doc.Url(sync_package_server.pkgsvr_url) + doc.Period(sync_package_server.period) + doc.Description(sync_package_server.description) + end + } + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def addDistribution + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + dist_name = change_item[:DistributionName] + if dist_name.nil? or dist_name.empty? then + errmsg = "Can't find [#{dist_name}] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + dist = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + if dist.nil? + dist = Distribution.new + dist.name = change_item[:DistributionName] + dist.pkgsvr_url = change_item[:URL] + dist.pkgsvr_addr = change_item[:Address] + dist.status = change_item[:DistStatus] + dist.description = change_item[:Description] + dist.save + + sync_pkg_svr = SyncPkgServer.new + sync_pkg_svr.distribution_id = dist.id + sync_pkg_svr.pkgsvr_url = change_item[:SyncPkgSvrUrl] + sync_pkg_svr.period = change_item[:SyncPkgSvrPeriod] + sync_pkg_svr.description = change_item[:SyncPkgSvrDescription] + sync_pkg_svr.save + else + errmsg = "Distribution[#{dist_name}] already exist" + end + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :json => { :error=> errmsg }, :status => 406 + end + end + + def removeDistribution + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + dist_name = change_item[:DistributionName] + if dist_name.nil? or dist_name.empty? then + errmsg = "Can't find [#{dist_name}] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + dist = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + if dist.nil? + errmsg = "Distribution[#{dist_name}] not exist" + else + # first, remove sync package server + sync_pkg_svr = SyncPkgServer.find(:first, :conditions => ["distribution_id = ?", dist.id]) + + if not sync_pkg_svr.nil? + sync_pkg_svr.destroy + end + + # remove distribution + dist.destroy + end + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :json => { :error=> errmsg }, :status => 406 + end + end + + def modifyDistribution + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + dist_name = change_item[:DistributionName] + if dist_name.nil? or dist_name.empty? then + errmsg = "Can't find [#{dist_name}] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + dist = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + if dist.nil? + errmsg = "Distribution[#{dist_name}] not exist" + else + dist.pkgsvr_url = change_item[:URL] + dist.pkgsvr_addr = change_item[:Address] + dist.status = change_item[:DistStatus] + dist.description = change_item[:Description] + dist.save + + sync_pkg_svr_url = change_item[:SyncPkgSvrUrl] + sync_pkg_svr_period = change_item[:SyncPkgSvrPeriod] + sync_pkg_svr_description = change_item[:SyncPkgSvrDescription] + sync_pkg_svr = SyncPkgServer.find(:first, :conditions => ["distribution_id = ?", dist.id]) + if not sync_pkg_svr_url.nil? and not sync_pkg_svr_url.empty? + if sync_pkg_svr.nil? + sync_pkg_svr = SyncPkgServer.new + end + sync_pkg_svr.distribution_id = dist.id + sync_pkg_svr.pkgsvr_url = sync_pkg_svr_url + sync_pkg_svr.period = sync_pkg_svr_period + sync_pkg_svr.description = sync_pkg_svr_description + sync_pkg_svr.save + elsif not sync_pkg_svr.nil? and not sync_pkg_svr_url.nil? and sync_pkg_svr_url.empty? + # if sync_pkg_svr is already exist and modified sync_pkg_svr_url is empty then remove it + sync_pkg_svr.destroy + end + end + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :json => { :error=> errmsg }, :status => 406 + end + end + + def fullBuildDistribution + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + dist_name = change_item[:DistributionName] + if dist_name.nil? or dist_name.empty? then + errmsg = "Can't find [#{dist_name}] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + dist = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + if dist.nil? + errmsg = "Distribution[#{dist_name}] not exist" + end + + server_config = Server_config.find(:first, :conditions => ["property = \"id\""]) + if server_config.nil? + errmsg = "Server name can't find" + else + server_name = server_config.value + + if server_name.nil? or server_name.empty? + errmsg = "Server name can't find" + end + end + + if errmsg.empty? + Utils.sbi_fullbuild_command(server_name, dist_name) + render :json => { :success => "OK!" } + else + render :json => { :error=> errmsg }, :status => 406 + end + end +end diff --git a/dibs-web/app/controllers/admin_group_controller.rb b/dibs-web/app/controllers/admin_group_controller.rb new file mode 100644 index 0000000..5818e1b --- /dev/null +++ b/dibs-web/app/controllers/admin_group_controller.rb @@ -0,0 +1,240 @@ +=begin + admin_group_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class AdminGroupController < ApplicationController + + before_filter :check_login_status, :check_admin_group + skip_before_filter :check_admin_group, :only => [:queryAllGroup] + + def queryAllGroup + project_list = Project.all(:order => "name") + group_list = Group.all + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + if not group_list.nil? + group_list.each do |group| + group_access_list = GroupProjectAccess.find(:all, :conditions => ["group_id = ?", group.id]) + + doc.Group { + doc.GroupName(group.name) + doc.AdminFlag(group.admin) + doc.Description(group.description) + + if not group_access_list.nil? + group_access_list.each do |group_right| + project = Project.find(:first, :conditions => ["id = ?", group_right.project_id]); + distribution = Distribution.find(:first, :conditions => ["id = ?", project.distribution_id]); + if not project.nil? + doc.AccessableProject { + doc.ProjectName(project.name) + doc.ProjectDistribution(distribution.name) + } + end + end + end + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def queryGroupInfo + group_name = params[:groupName] + if group_name.nil? or group_name.empty? + render :text => "Group name is empty", :content_type => "text/xml", :status => 406 + return + end + + group = Group.find(:first, :conditions => ["name = ?", group_name]) + if group.nil? + render :text => "Can't find group : #{group_name}", :content_type => "text/xml", :status => 406 + return + end + + project_list = Project.all(:order => "name") + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + if not project_list.nil? + project_list.each do |project| + distribution = Distribution.find(:first, :conditions => ["id = ?", project.distribution_id]); + doc.Project{ + doc.Name(project.name) + doc.Id(project.id) + doc.DistName(distribution.name) + } + end + end + + doc.Group { + doc.Name(group.name) + + group_access_list = GroupProjectAccess.find(:all, :conditions => ["group_id = ?", group.id]) + + if not group_access_list.nil? and not group_access_list.empty? + project_id_list = [] + group_access_list.each do |group_right| + project_id_list.push group_right.project_id + end + + doc.ProjectList(project_id_list.join(",")) + end + } + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def modifyGroup + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + group_name = change_item[:GroupName] + if group_name.nil? or group_name.empty? + render :text => "Group name is invalid", :status => 406 + return + else + group = Group.find(:first, :conditions => ["name= ?", group_name]) + end + + if group.nil? + errmsg = "Can't find group" + else + new_group_name = change_item[:NewGroupName] + admin_flag = change_item[:AdminFlag] + description = change_item[:Description] + project_id_list = change_item[:ProjectList].split(",") + + group.name = new_group_name + group.admin = admin_flag + group.description = description + group.save + + GroupProjectAccess.delete_all(["group_id = ?", group.id]) + + project_id_list.each do |project_id| + item = GroupProjectAccess.new + item.group_id = group.id + item.project_id = project_id + item.build = "TRUE" + item.save + end + end + + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :text => errmsg, :status => 406 + end + end + + def removeGroup + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + group_name = change_item[:GroupName] + if group_name.nil? or group_name.empty? + render :text => "Group name is invalid", :status => 406 + return + else + group = Group.find(:first, :conditions => ["name= ?", group_name]) + end + + if group.nil? + errmsg = "Can't find group" + else + user_group = UserGroup.find(:first, :conditions => ["group_id = ?", group.id]) + if user_group.nil? + GroupProjectAccess.delete_all(["group_id = ?", group.id]) + group.destroy + else + errmsg = "Can't remove. #{group_name} has users." + end + end + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :text => errmsg, :status => 406 + end + end + + def addGroup + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + group_name = change_item[:GroupName] + if group_name.nil? or group_name.empty? + render :text => "Group name is invalid", :status => 406 + return + else + group = Group.find(:first, :conditions => ["name= ?", group_name]) + end + + if not group.nil? + errmsg = "Group already exist" + else + group = Group.new + group.name = group_name + group.admin = change_item[:AdminFlag] + group.description = change_item[:Description] + group.save + + project_id_list = change_item[:ProjectList].split(",") + project_id_list.each do |project_id| + group_project_access = GroupProjectAccess.new + group_project_access.group_id = group.id + group_project_access.project_id = project_id + group_project_access.save + end + end + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :text => errmsg, :status => 406 + end + end +end diff --git a/dibs-web/app/controllers/admin_project_controller.rb b/dibs-web/app/controllers/admin_project_controller.rb new file mode 100644 index 0000000..a0f7b72 --- /dev/null +++ b/dibs-web/app/controllers/admin_project_controller.rb @@ -0,0 +1,301 @@ +=begin + admin_project_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class AdminProjectController < ApplicationController + def queryAllProject + project_list = Project.all(:order => "name") + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + if not project_list.nil? + project_list.each do |project| + distribution = Distribution.find(:first, :conditions => ["id = ?", project.distribution_id]); + doc.Project{ + doc.Name(project.name) + doc.Id(project.id) + doc.DistName(distribution.name) + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def queryProjectsInDistributionForAdmin + dist_name = params[:distribution] + + if dist_name.nil? or dist_name.empty? + render :text => "Distribution name is empty", :content_type => "text/xml", :status => 406 + return + end + + # get distribution + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + if distribution.nil? + render :text => "Can't find distribution : #{dist_name}", :content_type => "text/xml", :status => 406 + return + end + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + #generate to XML + doc.Data{ + project_list = Project.find_by_sql("SELECT projects.id + , projects.name + , projects.ptype + FROM projects + , distributions + WHERE distributions.name = \"#{dist_name}\" + AND distributions.id = projects.distribution_id + ORDER BY projects.name") + if not project_list.nil? + project_list.each do |project| + doc.Project { + doc.ProjectName(project.name) + doc.Type(project.ptype) + + os_list = ProjectOs.find(:all, :conditions => ["project_id = ?", project.id]) + if not os_list.nil? then + os_list.each do |os| + supported_os = SupportedOs.find(:first, :conditions => ["id = ?", os.supported_os_id]) + doc.OS(supported_os.name) + end + end + + case project.ptype.upcase + when "GIT" + git = ProjectGit.find(:first, :conditions => ["project_id = ?", project.id]) + if not git.nil? then + doc.GitRepos(git.git_repos) + doc.GitBranch(git.git_branch) + end + + when "BINARY" + bin = ProjectBin.find(:first, :conditions => ["project_id = ?", project.id]) + if not bin.nil? then + doc.PackageName(bin.pkg_name) + end + end + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def addProject + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + project_name = change_item[:Name] + project_type = change_item[:ProjectType].upcase + project_dist_name = change_item[:Distribution] + project_password = change_item[:ProjectPass] + + if project_name.nil? or project_name.empty? then + errmsg = "Can't find [Name] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + distribution = Distribution.find(:first, :conditions => ["name = ?", project_dist_name]) + project = Project.find(:first, :conditions => ["name = ? and distribution_id = ? and ptype = ?", project_name, distribution.id, project_type]) + + if not project.nil? + errmsg = "project already exist" + render :json => { :error => errmsg }, :status => 406 + return + end + + if not project_type.eql? "GIT" and not project_type.eql? "BINARY" + errmsg = "project type is invalid" + render :json => { :error => errmsg }, :status => 406 + return + end + + project = Project.new + project.name = project_name + project.ptype = project_type + project.password = project_password + project.distribution_id = distribution.id + #TODO: set project user is admin. admin user id is '1' + project.user_id = 1 + project.save + + if not change_item[:OSNameList].nil? + os_name_list = change_item[:OSNameList].split(",") + os_name_list.each do |os_name| + supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name]) + #need check not found + project_os = ProjectOs.new + project_os.project_id = project.id + project_os.supported_os_id = supported_os.id + project_os.save + end + end + + case project.ptype + when "GIT" + git = ProjectGit.new + git.project_id = project.id + git.git_repos = change_item[:Address] + git.git_branch = change_item[:Branch] + git.save + when "BINARY" + binary = ProjectBin.new + binary.project_id = project.id + binary.pkg_name = change_item[:PackageName] + binary.save + end + + render :json => { :success => "OK!" } + end + + def removeProject + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + if change_item[:Name].nil? or change_item[:Name].empty? then + errmsg = "Can't find [Name] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + dist_name = change_item[:Distribution] + project_name = change_item[:Name] + project_type = change_item[:ProjectType] + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + project = Project.find(:first, :conditions => ["name = ? and distribution_id = ?", project_name, distribution.id]) + + if project.nil? + errmsg = "project does not exist" + render :json => { :error => errmsg }, :status => 406 + return + end + + case project_type.upcase + when "GIT" + ProjectGit.delete_all(["project_id = ?", project.id]) + ProjectOs.delete_all(["project_id = ?", project.id]) + GroupProjectAccess.delete_all(["project_id = ?", project.id]) + when "BINARY" + ProjectBin.delete_all(["project_id = ?", project.id]) + GroupProjectAccess.delete_all(["project_id = ?", project.id]) + else + errmsg = "project type is invalid" + render :json => { :error => errmsg }, :status => 406 + return + end + + # remove project os + ProjectOs.delete_all(["project_id = ?", project.id]) + + # remove project + project.destroy + + render :json => { :success => "OK!" } + end + + def modifyProject + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + dist_name = change_item[:Distribution] + old_project_name = change_item[:Name] + project_type = change_item[:ProjectType].upcase + + if old_project_name.nil? or old_project_name.empty? then + errmsg = "Can't find [#{old_project_name}] information" + render :json => { :error => errmsg }, :status => 406 + return + end + + if not project_type.eql? "GIT" and not project_type.eql? "BINARY" + errmsg = "project type is invalid" + render :json => { :error => errmsg }, :status => 406 + return + end + + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + project = Project.find(:first, :conditions => ["name = ? and distribution_id = ? and ptype = ?", old_project_name, distribution.id, project_type]) + project.name = change_item[:NewProjectName] + project.password = change_item[:ProjectPass] + + # remove project os and reset project os + ProjectOs.delete_all(["project_id = ?", project.id]) + if not change_item[:OSNameList].nil? + os_name_list = change_item[:OSNameList].split(",") + os_name_list.each do |os_name| + supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name]) + #need check not found + project_os = ProjectOs.new + project_os.project_id = project.id + project_os.supported_os_id = supported_os.id + project_os.save + end + end + + case project_type + when "GIT" + project_git = ProjectGit.find(:first, :conditions => ["project_id = ?", project.id]) + if project_git.nil? + project_git.project_id = project.id + project_git = ProjectGit.new + end + project_git.git_repos = change_item[:ProjectAddress] + project_git.git_branch = change_item[:ProjectBranch] + project_git.save + + when "BINARY" + project_bin = ProjectBin.find(:first, :conditions => ["project_id = ?", project.id]) + if project_bin.nil? + project_bin = ProjectBin.new + project_bin.project_id = project.id + end + project_bin.pkg_name = change_item[:PackageName] + project_bin.save + end + + project.save + render :json => { :success => "OK!" } + end +end diff --git a/dibs-web/app/controllers/admin_server_controller.rb b/dibs-web/app/controllers/admin_server_controller.rb new file mode 100644 index 0000000..8efb20d --- /dev/null +++ b/dibs-web/app/controllers/admin_server_controller.rb @@ -0,0 +1,424 @@ +=begin + admin_server_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class AdminServerController < ApplicationController + def queryAllServer + # get full distribution list + server_config = Server_config.all + remote_build_servers = RemoteBuildServer.all + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + #generate to XML + doc.Data { + if not server_config.nil? + server_config.each do |info| + doc.ServerConfig { + doc.Property( info.property ) + doc.Value( info.value ) + } + end + end + + if not remote_build_servers.nil? + remote_build_servers.each do |server| + doc.RemoteBuildServer { + doc.Address(server.svr_addr) + supported_os = SupportedOs.find(:first, :conditions => ["id = ?", server.supported_os_id]) + if supported_os.nil? + doc.SupportedOS("") + else + doc.SupportedOS(supported_os.name) + end + doc.Status(server.status) + doc.MaxJobCount(server.max_job_count) + doc.WorkingJobCount(server.working_job_count) + doc.WaitingJobCount(server.waiting_job_count) + doc.Description(server.description) + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def addRemoteBuildServer + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + address = change_item[:Address] + description = change_item[:Description] + if address.nil? or address.empty? + errmsg = "Server address is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", address]) + + if server.nil? + server = RemoteBuildServer.new + server.svr_addr = address + server.description = description + server.save + + render :json => { :success => "OK!" } + else + errmsg = "Server already exist" + + render :json => { :error => errmsg }, :status => 406 + end + end + + def modifyRemoteBuildServer + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + address = change_item[:Address] + if address.nil? or address.empty? + errmsg = "Server address is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", address]) + + if server.nil? + errmsg = "Server does not exist" + else + new_address = change_item[:NewAddress] + description = change_item[:Description] + + # error check for server already exist + if not address.eql? new_address + new_server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", new_address]) + + if not new_server.nil? + errmsg = "Server already exist" + end + end + + server.svr_addr = new_address + server.description = description + server.save + end + + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :json => { :error => errmsg }, :status => 406 + end + end + + def removeRemoteBuildServer + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + address = change_item[:Address] + if address.nil? or address.empty? + errmsg = "Server address is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", address]) + + if server.nil? + errmsg = "Server does not exist" + render :json => { :error => errmsg }, :status => 406 + else + server.destroy + render :json => { :success => "OK!" } + end + end + + def addOsCategory + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + name = change_item[:Name] + if name.nil? or name.empty? + errmsg = "Os category name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + osCategory = OsCategory.find(:first, :conditions => ["name = ?", name]) + + if osCategory.nil? + osCategory= OsCategory.new + osCategory.name = name + osCategory.save + + render :json => { :success => "OK!" } + else + errmsg = "Os category already exist" + + render :json => { :error => errmsg }, :status => 406 + end + end + + def removeOsCategory + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + name = change_item[:Name] + if name.nil? or name.empty? + errmsg = "Os category name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + osCategory = OsCategory.find(:first, :conditions => ["name = ?", name]) + + if osCategory.nil? + errmsg = "Can't find os category" + render :json => { :error => errmsg }, :status => 406 + else + osCategory.destroy + render :json => { :success => "OK!" } + end + end + + def addSupportedOS + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + os_name = change_item[:Name] + category_name = change_item[:OsCategory] + if os_name.nil? or os_name.empty? + errmsg = "Os name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + if category_name.nil? or category_name.empty? + errmsg = "Os category is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + os_category = OsCategory.find(:first, :conditions => ["name = ?", category_name]) + supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name]) + + if os_category.nil? + errmsg = "Os category does not exist" + + render :json => { :error => errmsg }, :status => 406 + elsif not supported_os.nil? + errmsg = "supported os already exist" + + render :json => { :error => errmsg }, :status => 406 + else + supported_os = SupportedOs.new + supported_os.name = os_name + supported_os.os_category_id = os_category.id + supported_os.save + + render :json => { :success => "OK!" } + end + end + + def removeSupportedOS + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + os_name = change_item[:Name] + if os_name.nil? or os_name.empty? + errmsg = "Os name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name]) + + if supported_os.nil? + errmsg = "supported os does not exist" + + render :json => { :error => errmsg }, :status => 406 + else + supported_os.destroy + + render :json => { :success => "OK!" } + end + end + + def modifySupportedOS + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + os_name = change_item[:Name] + new_os_name = change_item[:NewName] + category_name = change_item[:OsCategory] + if os_name.nil? or os_name.empty? + errmsg = "Os name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + os_category = OsCategory.find(:first, :conditions => ["name = ?", category_name]) + supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name]) + + if os_category.nil? + errmsg = "Os category does not exist" + + render :json => { :error => errmsg }, :status => 406 + elsif supported_os.nil? + errmsg = "supported os does not exist" + + render :json => { :error => errmsg }, :status => 406 + else + if not os_name.eql? new_os_name + new_supported_os = SupportedOs.find(:first, :conditions => ["name = ?", new_os_name]) + if new_supported_os.nil? + supported_os.name = new_os_name + else + errmsg = "supported os already exist" + + render :json => { :error => errmsg }, :status => 406 + return + end + end + + supported_os.os_category_id = os_category.id + supported_os.save + + render :json => { :success => "OK!" } + end + end + + def addServerInfo + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + property = change_item[:Property] + value = change_item[:Value] + if property.nil? or property.empty? + errmsg = "Property name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + if value.nil? or value.empty? + errmsg = "Value is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + config = Server_config.find(:first, :conditions => ["property = ?", property]) + + if not config.nil? + errmsg = "Config alerady exist" + render :json => { :error => errmsg }, :status => 406 + else + config = Server_config.new + config.property = property + config.value = value + config.save + + render :json => { :success => "OK!" } + end + end + + def modifyServerInfo + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + property = change_item[:Property] + value = change_item[:Value] + if property.nil? or property.empty? + errmsg = "Property is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + if value.nil? or value.empty? + errmsg = "Value is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + config = Server_config.find(:first, :conditions => ["property = ?", property]) + + if config.nil? + errmsg = "Config does not exist" + render :json => { :error => errmsg }, :status => 406 + else + config.value = value + config.save + + render :json => { :success => "OK!" } + end + end + + def removeServerInfo + change_group_list = params[:ChangeInfoList] + change_item = change_group_list[0] + errmsg = "" + + property = change_item[:Property] + if property.nil? or property.empty? + errmsg = "Property is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + # get server for error check + config = Server_config.find(:first, :conditions => ["property = ?", property]) + + if config.nil? + errmsg = "Property does not exist" + render :json => { :error => errmsg }, :status => 406 + else + config.destroy + render :json => { :success => "OK!" } + end + end + +end diff --git a/dibs-web/app/controllers/admin_user_controller.rb b/dibs-web/app/controllers/admin_user_controller.rb new file mode 100644 index 0000000..7f4af7e --- /dev/null +++ b/dibs-web/app/controllers/admin_user_controller.rb @@ -0,0 +1,142 @@ +=begin + admin_user_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class AdminUserController < ApplicationController + + before_filter :check_login_status, :check_admin_group + + def queryAllUser + user_list = User.all(:order => "name") + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + if not user_list.nil? + user_list.each do |user| + doc.User { + doc.Name(user.name) + doc.Email(user.email) + doc.GroupList { + group_list = Group.find_by_sql("SELECT groups.name + , groups.admin + , groups.description + FROM users + , user_groups + , groups + WHERE users.id = user_groups.user_id + AND user_groups.group_id = groups.id + AND users.email = \"#{user.email}\"") + group_list.each { |group| + doc.GroupName(group.name) + } + } + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def modifyUser + change_user_list = params[:ChangeInfoList] + change_item = change_user_list[0] + errmsg = "" + + email = change_item[:Email] + group_name = change_item[:GroupName] + user_name = change_item[:UserName] + + if email.nil? or email.empty? + render :text => "Email is invalid", :status => 406 + return + else + user = User.find(:first, :conditions => ["email = ?", email]) + + if user.nil? + errmsg = "Can't find user information" + render :text => errmsg, :status => 406 + return + end + end + + if group_name.nil? or group_name.empty? + render :text => "Group name is invalid", :status => 406 + return + else + group = Group.find(:first, :conditions => ["name = ?", group_name]) + if group.nil? + errmsg = "Can't find group information" + render :text => errmsg, :status => 406 + return + end + end + + user.name = user_name + user.save + + UserGroup.delete_all(["user_id = ?", user.id]) + + user_groups = UserGroup.new + + user_groups.user_id = user.id + user_groups.group_id = group.id + user_groups.status = "ACTIVE" + user_groups.save + + render :json => { :success => "OK!" } + end + + def removeUser + change_user_list = params[:ChangeInfoList] + change_item = change_user_list[0] + errmsg = "" + + email = change_item[:Email] + if email.nil? or email.empty? + render :text => "Email is invalid", :status => 406 + return + else + user = User.find(:first, :conditions => ["email = ?", email]) + end + + if user.nil? + errmsg = "Can't find user information" + render :text => errmsg, :status => 406 + else + UserGroup.delete_all(["user_id = ?", user.id]) + + user.destroy + render :json => { :success => "OK!" } + end + end +end diff --git a/dibs-web/app/controllers/application_controller.rb b/dibs-web/app/controllers/application_controller.rb new file mode 100644 index 0000000..1ad4921 --- /dev/null +++ b/dibs-web/app/controllers/application_controller.rb @@ -0,0 +1,162 @@ +=begin + application_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class ApplicationController < ActionController::Base + #protect_from_forgery + + JOBS_STAUTS_WAITING = "WAITING" + + helper_method :current_user + + def get_user_id + if @current_user.nil? + current_user + end + + if not @current_user.nil? + return @current_user.id + else + return nil + end + end + + def get_user_email + if @current_user.nil? + current_user + end + + if not @current_user.nil? + return @current_user.email + else + return nil + end + end + + def get_group_list(email) + if not email.nil? + group_list = Group.find_by_sql("SELECT groups.id + , groups.name + , groups.admin + , groups.description + FROM users + , user_groups + , groups + WHERE users.id = user_groups.user_id + AND user_groups.group_id = groups.id + AND users.email = \"#{email}\"") + return group_list + else + return nil + end + end + + def is_admin(email) + if not email.nil? + group = Group.find_by_sql("SELECT count(*) AS cnt + FROM users + , user_groups + , groups + WHERE users.id = user_groups.user_id + AND user_groups.group_id = groups.id + AND groups.admin = 'TRUE' + AND users.email = \"#{email}\"") + if group[0].cnt > 0 + return TRUE + end + end + + return FALSE + end + + def generate_xml_header(doc) + email = get_user_email + group_list = get_group_list(email) + if is_admin(email) + admin = "TRUE" + else + admin = "FALSE" + end + + doc.Header { + doc.UserInfo { + doc.Email(email) + doc.Name(@current_user.name) + doc.Admin(admin) + doc.GroupList { + group_list.each { |group| + doc.Group { + doc.GroupName(group.name) + doc.GroupAdmin(group.admin) + doc.GroupDescription(group.description) + } + } + } + } + } + end + + private + def current_user + @current_user ||= User.find(:first, :conditions => {:email => session[:user_email]}) if session[:user_email] + end + + def check_login_status + if session[:user_email].nil? then + render :nothing => true, :status => 401 + return + end + end + + def check_admin_group + if session[:user_email].nil? or session[:user_email].empty? then + render :nothing => true, :status => 401 + return false + else + admin = "FALSE" + user_email = session[:user_email] + + user = User.find(:first, :conditions => ["email = ?", user_email]) + + group_list = get_group_list(user.email) + + group_list.each {|group| + if group.admin == "TRUE" + admin = "TRUE" + break; + end + } + + if user.nil? or admin != "TRUE" + render :nothing => true, :status => 401 + return false + end + end + + return true + end +end diff --git a/dibs-web/app/controllers/jobs_controller.rb b/dibs-web/app/controllers/jobs_controller.rb new file mode 100644 index 0000000..b4f3797 --- /dev/null +++ b/dibs-web/app/controllers/jobs_controller.rb @@ -0,0 +1,634 @@ +=begin + jobs_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class JobsController < ApplicationController + + before_filter :check_login_status + + QUERY_CNT = 30 + + def list + end + + def listAll + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + listQuery(doc, "QUERY", params[:distribution], params[:status], params[:lastID], "", "") + } + } + render :text => out_string, :content_type => "text/xml" + end + + def listSearchUser + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + listQuery(doc, "QUERY", params[:distribution], params[:status], params[:lastID], params[:user], "") + } + } + render :text => out_string, :content_type => "text/xml" + end + + def listSearchGroup + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + listQueryGroup(doc, "QUERY", params[:distribution], params[:status], params[:lastID], params[:group]) + } + } + render :text => out_string, :content_type => "text/xml" + end + + def listSearchProject + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + listQueryProject(doc, "QUERY", params[:distribution], params[:status], params[:lastID], params[:project]) + } + } + render :text => out_string, :content_type => "text/xml" + end + + def listSearchDate + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + listQuery(doc, "QUERY", params[:distribution], params[:status], params[:lastID], "", params[:date]) + } + } + render :text => out_string, :content_type => "text/xml" + end + + def updateList + condition = params[:Condition] + param = params[:Param] + distribution = params[:Distribution] + status = params[:Status] + latest_id = params[:LatestId] + working_job_list = params[:WorkingJobId] + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + #new job list + case condition + when "all" + listQuery(doc, "UPDATE", distribution, status, latest_id, "", "") + when "user" + listQuery(doc, "UPDATE", distribution, status, latest_id, param, "") + when "group" + listQueryGroup(doc, "UPDATE", distribution, status, latest_id, param) + when "project" + listQueryProject(doc, "UPDATE", distribution, status, latest_id, param) + when "date" + listQuery(doc, "UPDATE", distribution, status, latest_id, "", param) + else + end + + # working job list for update + doc.WorkingJobList { + if not working_job_list.nil? + working_job_list.each do |job_id| + job = get_job_info(job_id) + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute(job.job_attribute) + doc.ParentJobId(job.parent_job_id) + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + + if job.job_attribute == "MULTI" + child_jobs = get_child_job_info(job.job_id) + child_jobs.each {|job| + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute("CHILD") + doc.ParentJobId(job.parent_job_id) + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + } + end + end + end + } + } + } + + render :text => out_string, :content_type => "text/xml" + + end + + def listQuery(doc, query_type, distribution, status, last_id, user, date) + condition = "" + + if(distribution == "ALL") + distribution = "%" + end + + if(status == "ALL") + status = "'FINISHED', 'JUST_CREATED', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING', 'ERROR', 'CANCELED'" + elsif(status == "SUCCESS") + status = "'FINISHED'" + elsif(status == "WORKING") + status = "'JUST_CREATE', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING'" + elsif(status == "ERROR") + status = "'ERROR', 'CANCELED'" + end + + if(query_type == "QUERY") + if(last_id == "LATEST") + last_job_id = Job.maximum(:id) + if last_job_id.nil? + last_job_id = 0 + end + else + last_job_id = last_id.to_i - 1 + end + condition = "jobs.id <= #{last_job_id}" + else + condition = "jobs.id > #{last_id}" + end + + user = user + "%" + + date = date + "%" + + jobs = Job.find_by_sql("SELECT jobs.id + , CASE WHEN jobs.jtype like 'MULTI%' THEN 'MULTI' + ELSE 'SINGLE' END AS job_attribute + FROM jobs + LEFT JOIN projects + ON jobs.project_id = projects.id + LEFT JOIN users + ON jobs.user_id = users.id + LEFT JOIN supported_os + ON jobs.supported_os_id = supported_os.id + LEFT JOIN distributions + ON jobs.distribution_id = distributions.id + LEFT JOIN remote_build_servers + ON jobs.remote_build_server_id = remote_build_servers.id + LEFT JOIN sources + ON jobs.source_id = sources.id + WHERE #{condition} + AND jobs.parent_job_id IS NULL + AND jobs.status in (#{status}) + AND users.name like '#{user}' + AND distributions.name like '#{distribution}' + AND DATE(jobs.start_time) like '#{date}' + ORDER BY jobs.id DESC + LIMIT #{QUERY_CNT}") + + #generate to XML + doc.JobList { + jobs.each {|job_list| + job = get_job_info(job_list.id) + + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute(job_list.job_attribute) + doc.ParentJobId(job.parent_job_id) + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + + if job_list.job_attribute == "MULTI" + child_jobs = get_child_job_info(job.job_id) + child_jobs.each {|job| + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute("CHILD") + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + } + end + } + } + end + + def listQueryGroup(doc, query_type, distribution, status, last_id, group) + + if(distribution == "ALL") + distribution = "%" + end + + if(status == "ALL") + status = "'FINISHED', 'JUST_CREATED', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING', 'ERROR', 'CANCELED'" + elsif(status == "SUCCESS") + status = "'FINISHED'" + elsif(status == "WORKING") + status = "'JUST_CREATE', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING'" + elsif(status == "ERROR") + status = "'ERROR', 'CANCELED'" + end + + if(query_type == "QUERY") + if(last_id == "LATEST") + last_job_id = Job.maximum(:id) + if last_job_id.nil? + last_job_id = 0 + end + else + last_job_id = last_id.to_i - 1 + end + condition = "jobs.id <= #{last_job_id}" + else + condition = "jobs.id > #{last_id}" + end + + group = group + "%" + + jobs = Job.find_by_sql("SELECT jobs.id + , CASE WHEN jobs.jtype like 'MULTI%' THEN 'MULTI' + ELSE 'SINGLE' END AS job_attribute + FROM jobs + LEFT JOIN distributions ON jobs.distribution_id = distributions.id + WHERE #{condition} + AND jobs.parent_job_id IS NULL + AND distributions.name like '#{distribution}' + AND jobs.status in (#{status}) + AND jobs.user_id IN (SELECT users.id + FROM users + LEFT JOIN user_groups ON user_groups.user_id = users.id + LEFT JOIN groups ON groups.id = user_groups.group_id + WHERE groups.name LIKE '#{group}') + ORDER BY jobs.id DESC + LIMIT #{QUERY_CNT}") + + #generate to XML + doc.Data { + doc.JobList { + jobs.each {|job_list| + job = get_job_info(job_list.id) + + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute(job_list.job_attribute) + doc.ParentJobId(job.parent_job_id) + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + + if job_list.job_attribute == "MULTI" + child_jobs = get_child_job_info(job.job_id) + child_jobs.each {|job| + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute("CHILD") + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + } + end + } + } + } + end + + def listQueryProject(doc, query_type, distribution, status, last_id, project) + if(distribution == "ALL") + distribution = "%" + end + + if(status == "ALL") + status = "'FINISHED', 'JUST_CREATED', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING', 'ERROR', 'CANCELED'" + elsif(status == "SUCCESS") + status = "'FINISHED'" + elsif(status == "WORKING") + status = "'JUST_CREATE', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING'" + elsif(status == "ERROR") + status = "'ERROR', 'CANCELED'" + end + + if(query_type == "QUERY") + if(last_id == "LATEST") + last_job_id = Job.maximum(:id) + if last_job_id.nil? + last_job_id = 0 + end + else + last_job_id = last_id.to_i - 1 + end + condition = "jobs.id <= #{last_job_id}" + else + condition = "jobs.id > #{last_id}" + end + + project = project + "%" + + jobs = Job.find_by_sql("SELECT jobs.id + , CASE WHEN jobs.jtype like \"MULTI%\" THEN \"MULTI\" + ELSE \"SINGLE\" END \"job_attribute\" + FROM jobs + LEFT JOIN projects + ON jobs.project_id = projects.id + LEFT JOIN users + ON jobs.user_id = users.id + LEFT JOIN supported_os + ON jobs.supported_os_id = supported_os.id + LEFT JOIN distributions + ON jobs.distribution_id = distributions.id + LEFT JOIN remote_build_servers + ON jobs.remote_build_server_id = remote_build_servers.id + LEFT JOIN sources + ON jobs.source_id = sources.id + WHERE #{condition} + AND jobs.status IN (#{status}) + AND projects.name like '#{project}' + ORDER BY jobs.id DESC + LIMIT #{QUERY_CNT}") + + #generate to XML + doc.Data { + doc.JobList { + jobs.each {|job_list| + job = get_job_info(job_list.id) + + doc.Job { + doc.Id(job.job_id) + doc.Distribution(job.distribution_name) + doc.ProjectName(job.project_name) + doc.JobType(job.job_type) + doc.JobAttribute(job_list.job_attribute) + doc.ParentJobId(job.parent_job_id) + doc.Os(job.supported_os_name) + doc.Status(job.status) + doc.UserName(job.user_name) + doc.StartTime(job.start_time) + doc.EndTime(job.end_time) + } + } + } + } + end + + def get_job_info(job_id) + jobs = Job.find_by_sql("SELECT jobs.id AS job_id + , jobs.jtype AS job_type + , jobs.status AS status + , jobs.parent_job_id AS parent_job_id + , DATE_FORMAT(jobs.start_time, '%Y-%m-%d %H:%i:%s') AS start_time + , DATE_FORMAT(jobs.end_time, '%Y-%m-%d %H:%i:%s') AS end_time + , CASE WHEN jobs.jtype like \"MULTI%\" THEN \"MULTI\" + ELSE \"SINGLE\" END \"job_attribute\" + , projects.name AS project_name + , projects.ptype AS project_type + , projects.password AS project_password + , users.name AS user_name + , users.email AS user_email + , supported_os.name AS supported_os_name + , distributions.name AS distribution_name + , distributions.pkgsvr_url AS pkgsvr_url + , distributions.pkgsvr_addr AS pkgsvr_addr + , distributions.description AS distribution_desc + , remote_build_servers.svr_addr AS remote_build_server_addr + , remote_build_servers.description AS remote_build_server_desc + , sources.pkg_ver AS pkg_ver + , sources.location AS location + FROM jobs + LEFT JOIN projects + ON jobs.project_id = projects.id + LEFT JOIN users + ON jobs.user_id = users.id + LEFT JOIN supported_os + ON jobs.supported_os_id = supported_os.id + LEFT JOIN distributions + ON jobs.distribution_id = distributions.id + LEFT JOIN remote_build_servers + ON jobs.remote_build_server_id = remote_build_servers.id + LEFT JOIN sources + ON jobs.source_id = sources.id + WHERE jobs.id = #{job_id}") + return jobs[0] + end + + def get_child_job_info(parent_job_id) + job = Job.find_by_sql("SELECT jobs.id AS job_id + , jobs.jtype AS job_type + , jobs.status AS status + , jobs.parent_job_id AS parent_job_id + , DATE_FORMAT(jobs.start_time, '%Y-%m-%d %H:%i:%s') AS start_time + , DATE_FORMAT(jobs.end_time, '%Y-%m-%d %H:%i:%s') AS end_time + , projects.name AS project_name + , projects.ptype AS project_type + , users.name AS user_name + , users.email AS user_email + , supported_os.name AS supported_os_name + , distributions.name AS distribution_name + , distributions.pkgsvr_url AS pkgsvr_url + , distributions.pkgsvr_addr AS pkgsvr_addr + , distributions.description AS distribution_desc + , remote_build_servers.svr_addr AS remote_build_server_addr + , remote_build_servers.description AS remote_build_server_desc + , sources.pkg_ver AS pkg_ver + , sources.location AS location + FROM jobs + LEFT JOIN projects + ON jobs.project_id = projects.id + LEFT JOIN users + ON jobs.user_id = users.id + LEFT JOIN supported_os + ON jobs.supported_os_id = supported_os.id + LEFT JOIN distributions + ON jobs.distribution_id = distributions.id + LEFT JOIN remote_build_servers + ON jobs.remote_build_server_id = remote_build_servers.id + LEFT JOIN sources + ON jobs.source_id = sources.id + WHERE jobs.parent_job_id = #{parent_job_id}") + return job + end + + def log_more + @cursor = nil + @file = nil + + line_cnt = 999 + conti= 1 + id = params[:id] + puts id + line = params[:line].to_i + + # Get job information + job = get_job_info(id) + if job.nil? + render :text => "Not found Job ID #{id}", :status => 406 + end + + if job.job_type == "MULTIBUILD" + project_name = job.job_type + else + project_name = job.project_name + end + + # Get log file infomation + file_name = "log" + buildsvr_path = Server_config.find(:first, :conditions => ["property = ?", "path"]) + directory = "#{buildsvr_path.value}/jobs/#{id}" + + # create the file path + path = File.join(directory, file_name) + + # read the file + if File.exist?(path) + @cursor = File.size(path) + @file = File.open(path, 'r') + data = @file.readlines + end + + time = Time.new + timestamp = time.getlocal + + start_line = line + last_line = start_line + line_cnt + + #count line + tok = nil + IO.popen("wc -l #{path}") do |wc| + tok = wc.read.split(" ") + end + end_line = tok[0].to_i + + #check line + if last_line > end_line + last_line = end_line + end + + #read log file + temp = nil + if start_line < end_line + IO.popen("sed -n \"#{start_line},#{last_line}p\" #{path}") do |sed| + temp = sed.read + end + else + conti= 0 + end + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Responser { + generate_xml_header(doc) + doc.Data { + doc.JobId(id) + doc.Distribution(job.distribution_name) + doc.Project(project_name) + doc.Builder(job.user_name) + doc.Status(job.status) + doc.Time(timestamp) + doc.Continue(conti) + if temp + temp.each do |data| + doc.LogData(data, "Line" => line) + line = line + 1 + end + end + } + } + + render :text => out_string, :content_type => "text/xml" + end + + def cancelJob + id = params[:id] + + # get job information + job = get_job_info(id) + if job.nil? + render :text => "Not found Job ID #{id}", :status => 406 + return + end + + # Check job builder + if get_user_email != job.user_email + if not is_admin(get_user_email) + render :text => "You don't have authority to calcel.", :status => 406 + return + end + end + + # Excute command + begin + Utils.sbi_cancel_command(id, job.project_password) + rescue => e + render :text => e.message, :status => 406 + return + end + render :xml=> "OK" + end +end diff --git a/dibs-web/app/controllers/projects_controller.rb b/dibs-web/app/controllers/projects_controller.rb new file mode 100644 index 0000000..2bb8c94 --- /dev/null +++ b/dibs-web/app/controllers/projects_controller.rb @@ -0,0 +1,407 @@ +=begin + projects_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'json' + +class ProjectsController < ApplicationController + + layout :myLayout + before_filter :check_login_status + respond_to :json + + def myLayout + params[:action] == 'fileUpload' ? nil : 'application' + end + + + def buildProject + # get information : dist_name, project_hash, password + change_group_list = params[:ChangeInfoList] + + project_list = [] + os_list = [] + password_list = [] + + dist_name = nil + build_type = nil + + change_group_list.each do |change_item| + dist_name = change_item[:distribution] + build_type = change_item[:buildType] + project_name = change_item[:projectName] + os = change_item[:os] + + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + project = Project.find(:first, :conditions => ["name = ? AND distribution_id =?", project_name, distribution.id]) + + project_list.push project.name + password_list.push project.password + os_list.push os + end + + project_list.uniq! + os_list.uniq! + password_list.uniq! + + if (project_list.length > 1) or (not (project_list[0].nil? or project_list[0].empty?)) + # execute build command + begin + Utils.sbi_build_command(build_type, dist_name, project_list, os_list, password_list, get_user_email) + rescue => e + render :text => e.message, :status => 406 + return + end + + render :json => { :success => "OK!" } + else + render :text => "Can't build project", :status => 406 + end + + end + + def queryPackageInfo(project_id, os_id) + + source = Project.find_by_sql("SELECT sources.pkg_ver AS pkg_ver + , DATE_FORMAT(jobs.start_time, '%Y-%m-%d %H:%i:%s') AS start_time + , DATE_FORMAT(jobs.end_time, '%Y-%m-%d %H:%i:%s') AS end_time + , jobs.source_id AS source_id + , jobs.supported_os_id AS supported_os_id + , users.name AS user_name + , users.email AS user_email + FROM projects + , sources + , jobs + , users + WHERE projects.id = sources.project_id + AND jobs.source_id = sources.id + AND jobs.user_id = users.id + AND projects.id = #{project_id} + AND jobs.supported_os_id = #{os_id} + ORDER BY jobs.id DESC") + + + if source.nil? + return nil + else + return source[0] + end + end + + def checkUserAccessProject(user_id, project_id) + row = Project.find_by_sql("SELECT COUNT(*) AS cnt + FROM user_groups + , groups + , group_project_accesses + WHERE user_groups.group_id = groups.id + AND groups.id = group_project_accesses.group_id + AND user_groups.user_id = #{user_id} + AND group_project_accesses.project_id = #{project_id}") + if row[0].cnt > 0 + return TRUE + end + + return FALSE + end + + def queryProjectsInfoInDistribution + dist_name = params[:distribution] + + user_id = get_user_id + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + projects = Project.find(:all, :conditions => ["distribution_id = ?", distribution.id], :order => "name") + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + doc.ProjectList { + projects.each { |project| + doc.Project { + doc.Name(project.name) + doc.Type(project.ptype) + maintainer = User.find(:first, :conditions => ["id = ?", project.user_id]) + if not maintainer.nil? + doc.Maintainer(maintainer.email) + else + doc.Maintainer("") + end + + if checkUserAccessProject(user_id, project.id) + doc.GroupAccess("TRUE") + else + doc.GroupAccess("FALSE") + end + + os_list = ProjectOs.find(:all, :conditions => ["project_id = ?", project.id], :order => "supported_os_id") + os_list.each { |os| + doc.ProjectOs { + os_info = SupportedOs.find(:first, :conditions => ["id = ?", os.supported_os_id]) + doc.OsName(os_info.name) + + source = queryPackageInfo(project.id, os.supported_os_id) + if source.nil? + doc.Package { + doc.PackageName() + doc.PackageVersion() + doc.StartTime() + doc.EndTime() + doc.UserName() + doc.UserEmail() + } + else + packageList = Package.find(:all, :conditions => ["source_id = ? AND supported_os_id = ?", source.source_id, source.supported_os_id]) + + + packageList.each { |package| + doc.Package { + doc.PackageName(package.pkg_name) + doc.PackageVersion(source.pkg_ver) + doc.StartTime(source.start_time) + doc.EndTime(source.end_time) + doc.UserName(source.user_name) + doc.UserEmail(source.user_email) + } + } + end + } + } + } + } + } + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def queryRunningProjectsInfoInDistribution + dist_name = params[:distribution] + + running_project_list = Project.find_by_sql("SELECT projects.name + , projects.ptype + , jobs.status + , supported_os.name AS os_name + FROM jobs + , projects + , supported_os + , distributions + WHERE jobs.project_id = projects.id + AND distributions.name = \"#{dist_name}\" + AND projects.distribution_id = distributions.id + AND NOT jobs.status in ('FINISHED', 'ERROR', 'CANCELED') + AND supported_os.id = jobs.supported_os_id + ORDER BY jobs.id") + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + if not running_project_list.nil? + running_project_list.each do |run_project| + doc.RunProjectInfo { + doc.ProjectName(run_project.name) + doc.ProjectOs(run_project.os_name) + doc.ProjectType(run_project.ptype) + doc.Status(run_project.status) + } + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def queryJobStatus(project_id, supportes_os_id) + job = Job.find(:first, :conditions => ["status NOT IN ('FINISHED', 'ERROR') AND project_id = ? AND supported_os_id = ?", project_id, supported_os_id, ], :order => "id DESC") + if job.nil? + status = job.status + else + status = nil + end + return status + end + + def queryProjectsInDistribution + dist_name = params[:distribution] + + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + projects = Project.find(:all, :conditions => ["distribution_id = ?", distribution.id], :order => "name") + osList = SupportedOs.find(:all) + + # check can build + project_access_list = [] + + # get all my project + group_list = get_group_list(get_user_email) + + group_id_list = [] + group_list.each { |group| + group_id_list.push group.id + } + + group_name_list_string = + group_access_project_list = GroupProjectAccess.find(:all, :conditions => ["group_id in (?)", group_id_list.join(",") ]) + if not group_access_project_list.nil? + group_access_project_list.each do |access_project| + project_access_list.push access_project.project_id + end + end + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + doc.Data { + doc.BuildServerInfo { + if not osList.nil? + osList.each do |os| + doc.supportedOs(os.name) + end + end + } + + projects.each do |project| + if project.ptype.eql? "BINARY" + bin = ProjectBin.find(:first, :conditions => ["project_id = ?", project.id]) + if project_access_list.include? project.id + doc.BinaryProject { + doc.ProjectName(project.name) + if not bin.nil? then + doc.PackageName(bin.pkg_name) + end + } + else + doc.OtherBinaryProject { + doc.ProjectName(project.name) + if not bin.nil? then + doc.PackageName(bin.pkg_name) + end + } + end + else + buildOsNameList = [] + prjOsLists = ProjectOs.find(:all, :conditions => ["project_id = ?", project.id]) + + prjOsLists.each do |list| + supported_os = SupportedOs.find(:first, :conditions => ["id = ?", list.supported_os_id]) + buildOsNameList.push(supported_os.name) + end + + if project_access_list.include? project.id + doc.Project { + doc.ProjectName(project.name) + doc.OsList(buildOsNameList.join(",")) + } + else + doc.OtherProject { + doc.ProjectName(project.name) + doc.OsList(buildOsNameList.join(",")) + } + end + end + + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + + end + + def queryDistribution + distribution_list = [] + + # get full distribution list + distributions = Distribution.all + distributions.each {|distribution| + distribution_list.push distribution.name + } + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + if not distribution_list.nil? + distribution_list.each do |distribution| + doc.DistributionName(distribution) + end + end + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def projects + end + + def fileUpload + + end + + def binaryFileUpload + dist_name = params[:distribution] + project = params[:project] + uploaded_io = params[:file] + + file_path = Rails.root.join('public', 'data', uploaded_io.original_filename) + File.open(file_path, 'wb') do |file| + file.write(uploaded_io.read) + end + + distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name]) + project = Project.find(:first, :conditions => ["name = ? AND distribution_id =?", project, distribution.id]) + if project.nil? + render :nothing => true + return + end + + begin + Utils.sbi_register_command(distribution.name, file_path, project.password, get_user_email) + rescue => e + render :text => e.message, :status => 406 + return + end + + render :nothing => true + return + + render :text => uploaded_io.original_filename + " is uploaded.", + :content_type => "text/xml" + end + +end diff --git a/dibs-web/app/controllers/sessions_controller.rb b/dibs-web/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..9d90123 --- /dev/null +++ b/dibs-web/app/controllers/sessions_controller.rb @@ -0,0 +1,107 @@ +=begin + sessions_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class SessionsController < ApplicationController + def new + end + + def login + input_list = params[:ChangeInfoList] + input_item = input_list[0] + + create_session(input_item[:Email], input_item[:Password]) + end + + def create_session(email, password) + user = User.authenticate(email, password) + + if user + group_list = get_group_list(user.email) + if is_admin(user.email) + admin = "TRUE" + else + admin = "FALSE" + end + + session[:user_email] = user.email + user_info = { :Message => 'Welcome!', + :Eamil => user.email, + :Name => user.name, + :Admin => admin, + } + group_info = nil + group_list.map { |group| + group_info = {:Group => [:GroupName => group.name, + :GroupAdmin => group.admin, + :GroupDescription => group.description] } + } + + render :json => { :Result => 'SUCCESS', :UserInfo => user_info, :GroupInfo => group_info} + puts user_info + else + render :json => { :Result => 'ERROR', :UserInfo => {:Message => 'Fail login'} } + end + return + end + + def logout + session[:user_email] = nil + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + + doc.LogOutInfo { + doc.Message("Welcome...") + doc.LogInTime("") + doc.LogOutTime("") + } + + render :text => out_string, + :content_type => "text/xml" + end + + def create + user = User.authenticate(params[:email], params[:password]) + + #generate to XML + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + + if user + session[:user_email] = user.email + redirect_to "/projects" + else + flash.now.alert = "Invalid email or password" + render "new" + end + end + + def destroy + session[:user_email] = nil + redirect_to root_url, :notice => "Logged out!" + end +end diff --git a/dibs-web/app/controllers/users_controller.rb b/dibs-web/app/controllers/users_controller.rb new file mode 100644 index 0000000..0b830a1 --- /dev/null +++ b/dibs-web/app/controllers/users_controller.rb @@ -0,0 +1,172 @@ +=begin + users_controller.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class UsersController < ApplicationController + + def new + @user = User.new(params[:user]) + end + + def create + @user = User.new(params[:user]) + + if @user.save + redirect_to "/projects", :notice => "Signed up!" + else + render :action => "new" + end + end + + def signup + change_list = params[:ChangeInfoList] + change_item = change_list[0] + + @user = User.new() + @user.email = change_item[:Email] + @user.name = change_item[:Name] + @user.password = change_item[:Password] + @user.password_confirmation = change_item[:PasswordConfirm] + + if @user.save + create_session(@user.email, @user.password) + else + render :json => { :error => "Error"}, :status => 406 + end + + end + + def create_session(email, password) + user = User.authenticate(email, password) + + if user + group_list = get_group_list(user.email) + if is_admin(user.email) + admin = "TRUE" + else + admin = "FALSE" + end + + session[:user_email] = user.email + user_info = { :Message => 'Welcome!', + :Eamil => user.email, + :Name => user.name, + :Admin => admin, + } + group_info = nil + group_list.map { |group| + group_info = {:Group => [:GroupName => group.name, + :GroupAdmin => group.admin, + :GroupDescription => group.description] } + } + + render :json => { :Result => 'SUCCESS', :UserInfo => user_info, :GroupInfo => group_info} + puts user_info + else + render :json => { :Result => 'ERROR', :UserInfo => {:Message => 'Fail login'} } + end + return + end + + def show + email = get_user_email + user = User.find(:first, :conditions => ["email = ?", email]) + + doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 ) + doc.Response { + generate_xml_header(doc) + + doc.Data { + doc.User { + doc.Name(user.name) + doc.Email(user.email) + doc.GroupList { + group_list = get_group_list(user.email) + group_list.each { |group| + doc.GroupName(group.name) + } + } + } + } + } + + #send_data + render :text => out_string, :content_type => "text/xml" + end + + def modify + change_list = params[:ChangeInfoList] + change_item = change_list[0] + errmsg = "" + + email = change_item[:Email] + name = change_item[:Name] + password = change_item[:Password] + password_confirm = change_item[:PasswordConfirm] + + if email != get_user_email + errmsg = "Can't modify email" + render :json => { :error => errmsg }, :status => 406 + return + end + + if email.nil? or email.empty? + errmsg = "Email is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + if name.nil? or name.empty? + errmsg = "Name is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + if password.nil? or password.empty? + errmsg = "Password is empty" + render :json => { :error => errmsg }, :status => 406 + return + end + + if password != password_confirm + errmsg = "Password is different" + render :json => { :error => errmsg }, :status => 406 + return + end + user = User.find(:first, :conditions => ["email = ?", email]) + user.name = name + user.password = password + user.password_confirmation = password_confirm + user.save + + if errmsg.empty? + render :json => { :success => "OK!" } + else + render :json => { :error => errmsg }, :status => 406 + end + end +end diff --git a/dibs-web/app/controllers/utils.rb b/dibs-web/app/controllers/utils.rb new file mode 100644 index 0000000..b0e5f4b --- /dev/null +++ b/dibs-web/app/controllers/utils.rb @@ -0,0 +1,130 @@ +=begin + utils.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +# constant +BUILD_SERVER_ADDRESS = "127.0.0.1" + +class Utils < ApplicationController + def Utils.sbi_build_command(sub_cmd, distribution, project_list, os_list, password_list, email) + dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) + dibs_config = Server_config.find(:first, :conditions => ["property = \"port\""]) + if dibs_config.nil? + raise RuntimeError, "Build sever not started" + else + dibs_address = BUILD_SERVER_ADDRESS + ":" + dibs_config.value + end + + options = "-d #{dibs_address} --async " + options = options + " -N #{project_list.join(",")} -D #{distribution} " + if (os_list.length > 1) or (not os_list[0].nil?) + options = options + " -o #{os_list.join(",")} " + end + if (password_list.length > 1) or (not (password_list[0].nil? or password_list[0].empty?)) + options = options + " -w #{password_list.join(",")} " + end + if not email.nil? + options = options + " -U #{email} " + end + + cmd = "#{dibs_path}/build-cli #{sub_cmd} #{options}" +puts "Build command" +puts "[[[#{cmd}]]]" + + return execute_shell_return(cmd) + end + + def Utils.sbi_register_command(distribution, file_path, password, email) + dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) + dibs_config = Server_config.find(:first, :conditions => ["property = \"port\""]) + if dibs_config.nil? + raise RuntimeError, "Build sever not started" + else + dibs_address = BUILD_SERVER_ADDRESS + ":" + dibs_config.value + end + + options = "-P #{file_path} -d #{dibs_address} -D #{distribution} --async " + if (not password.nil?) + options = options + " -w #{password}" + end + if not email.nil? + options = options + " -U #{email} " + end + + cmd = "#{dibs_path}/build-cli register #{options}" +puts "Register command" +puts "[[[#{cmd}]]]" + return execute_shell_return(cmd) + end + + def Utils.sbi_cancel_command(job_id, password) + dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) + dibs_config = Server_config.find(:first, :conditions => ["property = \"port\""]) + if dibs_config.nil? + raise RuntimeError, "Build sever not started" + else + dibs_address = BUILD_SERVER_ADDRESS + ":" + dibs_config.value + end + + if job_id.nil? + raise RuntimeError, "Invalid job id : #{job_id}" + end + + options = "-d #{dibs_address} " + options = options + " -j #{job_id}" + if (not password.nil?) + options = options + " -w #{password}" + end + + cmd = "#{dibs_path}/build-cli cancel #{options}" +puts "Cancel command" +puts "[[[#{cmd}]]]" + return execute_shell_return(cmd) + end + + def Utils.sbi_fullbuild_command(server_name, dist_name) + dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) + + options = "-n #{server_name} --dist #{dist_name} " + cmd = "#{dibs_path}/build-svr fullbuild #{options}" +puts "Fullbuild command" +puts "[[[#{cmd}]]]" + return execute_shell_return(cmd) + end + + def Utils.execute_shell_return(cmd) + result_lines = [] + ret = false + + # get result + IO.popen("#{cmd}") + #system "#{cmd}" + + return true + end + +end diff --git a/dibs-web/app/helpers/admin_distribution_helper.rb b/dibs-web/app/helpers/admin_distribution_helper.rb new file mode 100644 index 0000000..97c39f6 --- /dev/null +++ b/dibs-web/app/helpers/admin_distribution_helper.rb @@ -0,0 +1,2 @@ +module AdminDistributionHelper +end diff --git a/dibs-web/app/helpers/admin_group_helper.rb b/dibs-web/app/helpers/admin_group_helper.rb new file mode 100644 index 0000000..9561d3b --- /dev/null +++ b/dibs-web/app/helpers/admin_group_helper.rb @@ -0,0 +1,2 @@ +module AdminGroupHelper +end diff --git a/dibs-web/app/helpers/admin_helper.rb b/dibs-web/app/helpers/admin_helper.rb new file mode 100644 index 0000000..d5c6d35 --- /dev/null +++ b/dibs-web/app/helpers/admin_helper.rb @@ -0,0 +1,2 @@ +module AdminHelper +end diff --git a/dibs-web/app/helpers/admin_project_helper.rb b/dibs-web/app/helpers/admin_project_helper.rb new file mode 100644 index 0000000..7925981 --- /dev/null +++ b/dibs-web/app/helpers/admin_project_helper.rb @@ -0,0 +1,2 @@ +module AdminProjectHelper +end diff --git a/dibs-web/app/helpers/admin_server_helper.rb b/dibs-web/app/helpers/admin_server_helper.rb new file mode 100644 index 0000000..5c7d70a --- /dev/null +++ b/dibs-web/app/helpers/admin_server_helper.rb @@ -0,0 +1,2 @@ +module AdminServerHelper +end diff --git a/dibs-web/app/helpers/admin_user_helper.rb b/dibs-web/app/helpers/admin_user_helper.rb new file mode 100644 index 0000000..3edd72d --- /dev/null +++ b/dibs-web/app/helpers/admin_user_helper.rb @@ -0,0 +1,2 @@ +module AdminUserHelper +end diff --git a/dibs-web/app/helpers/application_helper.rb b/dibs-web/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/dibs-web/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/dibs-web/app/helpers/jobs_helper.rb b/dibs-web/app/helpers/jobs_helper.rb new file mode 100644 index 0000000..44c7bf6 --- /dev/null +++ b/dibs-web/app/helpers/jobs_helper.rb @@ -0,0 +1,2 @@ +module JobsHelper +end diff --git a/dibs-web/app/helpers/projects_helper.rb b/dibs-web/app/helpers/projects_helper.rb new file mode 100644 index 0000000..fc47f60 --- /dev/null +++ b/dibs-web/app/helpers/projects_helper.rb @@ -0,0 +1,4 @@ +module ProjectsHelper + def update_text(name) + end +end diff --git a/dibs-web/app/helpers/sessions_helper.rb b/dibs-web/app/helpers/sessions_helper.rb new file mode 100644 index 0000000..309f8b2 --- /dev/null +++ b/dibs-web/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/dibs-web/app/helpers/users_helper.rb b/dibs-web/app/helpers/users_helper.rb new file mode 100644 index 0000000..2310a24 --- /dev/null +++ b/dibs-web/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/dibs-web/app/mailers/.gitkeep b/dibs-web/app/mailers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/dibs-web/app/models/.gitkeep b/dibs-web/app/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/dibs-web/app/models/distribution.rb b/dibs-web/app/models/distribution.rb new file mode 100644 index 0000000..994dc84 --- /dev/null +++ b/dibs-web/app/models/distribution.rb @@ -0,0 +1,3 @@ +class Distribution < ActiveRecord::Base + attr_accessible :id, :name, :pkgsvr_url, :pkgsvr_addr, :status, :description +end diff --git a/dibs-web/app/models/group.rb b/dibs-web/app/models/group.rb new file mode 100644 index 0000000..55595be --- /dev/null +++ b/dibs-web/app/models/group.rb @@ -0,0 +1,5 @@ +class Group < ActiveRecord::Base +# has_many :user_groups +# has_many :users, :through => :user_groups + attr_accessible :name, :id +end diff --git a/dibs-web/app/models/group_project_access.rb b/dibs-web/app/models/group_project_access.rb new file mode 100644 index 0000000..dee4f5e --- /dev/null +++ b/dibs-web/app/models/group_project_access.rb @@ -0,0 +1,4 @@ +class GroupProjectAccess < ActiveRecord::Base + self.primary_key = 'group_id', 'project_id' + attr_accessible :group_id, :project_id, :build +end diff --git a/dibs-web/app/models/job.rb b/dibs-web/app/models/job.rb new file mode 100644 index 0000000..3c15994 --- /dev/null +++ b/dibs-web/app/models/job.rb @@ -0,0 +1,3 @@ +class Job < ActiveRecord::Base + attr_accessible :distribution_id, :id, :supported_os_id, :project_id, :status, :user_id, :remote_build_server_id, :parent_job_id, :source_id, :jtype, :start_time, :end_time +end diff --git a/dibs-web/app/models/os_category.rb b/dibs-web/app/models/os_category.rb new file mode 100644 index 0000000..a8fbee1 --- /dev/null +++ b/dibs-web/app/models/os_category.rb @@ -0,0 +1,4 @@ +class OsCategory < ActiveRecord::Base + set_table_name "os_category" + attr_accessible :id, :name +end diff --git a/dibs-web/app/models/package.rb b/dibs-web/app/models/package.rb new file mode 100644 index 0000000..7e6b44f --- /dev/null +++ b/dibs-web/app/models/package.rb @@ -0,0 +1,3 @@ +class Package < ActiveRecord::Base + attr_accessible :id, :pkg_name, :source_id, :supported_os_id +end diff --git a/dibs-web/app/models/project.rb b/dibs-web/app/models/project.rb new file mode 100644 index 0000000..1c9d56e --- /dev/null +++ b/dibs-web/app/models/project.rb @@ -0,0 +1,3 @@ +class Project < ActiveRecord::Base + attr_accessible :id, :distribution_id, :name, :ptype, :password +end diff --git a/dibs-web/app/models/project_bin.rb b/dibs-web/app/models/project_bin.rb new file mode 100644 index 0000000..3252b0c --- /dev/null +++ b/dibs-web/app/models/project_bin.rb @@ -0,0 +1,3 @@ +class ProjectBin < ActiveRecord::Base + attr_accessible :project_id, :pkg_name +end diff --git a/dibs-web/app/models/project_git.rb b/dibs-web/app/models/project_git.rb new file mode 100644 index 0000000..c0a5d4d --- /dev/null +++ b/dibs-web/app/models/project_git.rb @@ -0,0 +1,3 @@ +class ProjectGit < ActiveRecord::Base + attr_accessible :project_id, :git_repos, :git_branch +end diff --git a/dibs-web/app/models/project_os.rb b/dibs-web/app/models/project_os.rb new file mode 100644 index 0000000..670dab0 --- /dev/null +++ b/dibs-web/app/models/project_os.rb @@ -0,0 +1,4 @@ +class ProjectOs < ActiveRecord::Base + self.primary_key = 'project_id', 'supported_os_id' + attr_accessible :project_id, :supported_os_id +end diff --git a/dibs-web/app/models/remote_build_server.rb b/dibs-web/app/models/remote_build_server.rb new file mode 100644 index 0000000..b02b1e5 --- /dev/null +++ b/dibs-web/app/models/remote_build_server.rb @@ -0,0 +1,3 @@ +class RemoteBuildServer < ActiveRecord::Base + attr_accessible :id, :svr_addr, :description, :status, :max_job_count, :working_job_count, :waiting_job_count +end diff --git a/dibs-web/app/models/server_config.rb b/dibs-web/app/models/server_config.rb new file mode 100644 index 0000000..68f2df8 --- /dev/null +++ b/dibs-web/app/models/server_config.rb @@ -0,0 +1,3 @@ +class Server_config < ActiveRecord::Base + attr_accessible :property, :value +end diff --git a/dibs-web/app/models/source.rb b/dibs-web/app/models/source.rb new file mode 100644 index 0000000..f8bd214 --- /dev/null +++ b/dibs-web/app/models/source.rb @@ -0,0 +1,3 @@ +class Source < ActiveRecord::Base + attr_accessible :id, :location, :pkg_ver, :project_id +end diff --git a/dibs-web/app/models/supported_os.rb b/dibs-web/app/models/supported_os.rb new file mode 100644 index 0000000..c37b19f --- /dev/null +++ b/dibs-web/app/models/supported_os.rb @@ -0,0 +1,3 @@ +class SupportedOs < ActiveRecord::Base + attr_accessible :id, :os_category_id, :name +end diff --git a/dibs-web/app/models/sync_pkg_server.rb b/dibs-web/app/models/sync_pkg_server.rb new file mode 100644 index 0000000..0863806 --- /dev/null +++ b/dibs-web/app/models/sync_pkg_server.rb @@ -0,0 +1,3 @@ +class SyncPkgServer < ActiveRecord::Base + attr_accessible :description, :distribution_id, :id, :period, :pkgsvr_url +end diff --git a/dibs-web/app/models/sync_project.rb b/dibs-web/app/models/sync_project.rb new file mode 100644 index 0000000..b860a7a --- /dev/null +++ b/dibs-web/app/models/sync_project.rb @@ -0,0 +1,3 @@ +class SyncProject < ActiveRecord::Base + attr_accessible :project_id, :sync_pkg_server_id +end diff --git a/dibs-web/app/models/user.rb b/dibs-web/app/models/user.rb new file mode 100644 index 0000000..ebfb5f1 --- /dev/null +++ b/dibs-web/app/models/user.rb @@ -0,0 +1,29 @@ +class User < ActiveRecord::Base +# has_many :user_groups +# has_many :groups, :through => :user_groups + attr_accessible :id, :email, :password, :password_confirmation, :name + + attr_accessor :password + before_save :encrypt_password + + validates_uniqueness_of :email + validates_presence_of :email + validates_confirmation_of :password + validates_presence_of :password, :on => :create + + def self.authenticate(email, password) + user = find_by_email(email) + if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt) + user + else + nil + end + end + + def encrypt_password + if password.present? + self.password_salt = BCrypt::Engine.generate_salt + self.password_hash = BCrypt::Engine.hash_secret(password, password_salt) + end + end +end diff --git a/dibs-web/app/models/user_group.rb b/dibs-web/app/models/user_group.rb new file mode 100644 index 0000000..d963db5 --- /dev/null +++ b/dibs-web/app/models/user_group.rb @@ -0,0 +1,7 @@ +class UserGroup < ActiveRecord::Base +# belongs_to :users +# belongs_to :groups + self.primary_key = 'group_id' + self.primary_key = 'user_id' + attr_accessible :group_id, :status, :user_id +end diff --git a/dibs-web/config.ru b/dibs-web/config.ru new file mode 100644 index 0000000..536e8d2 --- /dev/null +++ b/dibs-web/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Dibs::Application diff --git a/dibs-web/config/application.rb b/dibs-web/config/application.rb new file mode 100644 index 0000000..1e8680c --- /dev/null +++ b/dibs-web/config/application.rb @@ -0,0 +1,62 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +if defined?(Bundler) + # If you precompile assets before deploying to production, use this line + Bundler.require(*Rails.groups(:assets => %w(development test))) + # If you want your assets lazily compiled in production, use this line + # Bundler.require(:default, :assets, Rails.env) +end + +module Dibs + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] + + # Enable escaping HTML in JSON. + config.active_support.escape_html_entities_in_json = true + + # Use SQL instead of Active Record's schema dumper when creating the database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql + + # Enforce whitelist mode for mass assignment. + # This will create an empty whitelist of attributes available for mass-assignment for all models + # in your app. As such, your models will need to explicitly whitelist or blacklist accessible + # parameters by using an attr_accessible or attr_protected declaration. + config.active_record.whitelist_attributes = true + + # Enable the asset pipeline + config.assets.enabled = true + + # Version of your assets, change this if you want to expire all your assets + config.assets.version = '1.0' + end +end diff --git a/dibs-web/config/boot.rb b/dibs-web/config/boot.rb new file mode 100644 index 0000000..4489e58 --- /dev/null +++ b/dibs-web/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/dibs-web/config/database.yml b/dibs-web/config/database.yml new file mode 100644 index 0000000..319f61e --- /dev/null +++ b/dibs-web/config/database.yml @@ -0,0 +1,46 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# development: +# adapter: sqlite3 +# database: db/development.sqlite3 +# pool: 5 +# timeout: 5000 +# +# # Warning: The database defined as "test" will be erased and +# # re-generated from your development database when you run "rake". +# # Do not set this db to the same as development or production. + test: + adapter: + encoding: + host: + port: + database: + username: + password: + pool: + timeout: + + production: + adapter: + encoding: + host: + port: + database: + username: + password: + pool: + timeout: + + development: + adapter: + encoding: + host: + port: + database: + username: + password: + pool: + timeout: diff --git a/dibs-web/config/environment.rb b/dibs-web/config/environment.rb new file mode 100644 index 0000000..b3360a8 --- /dev/null +++ b/dibs-web/config/environment.rb @@ -0,0 +1,7 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Dibs::Application.initialize! + +Rails.logger = Logger.new(STDOUT) diff --git a/dibs-web/config/environments/development.rb b/dibs-web/config/environments/development.rb new file mode 100644 index 0000000..f2b6b9b --- /dev/null +++ b/dibs-web/config/environments/development.rb @@ -0,0 +1,37 @@ +Dibs::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger + config.active_support.deprecation = :log + + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + config.active_record.auto_explain_threshold_in_seconds = 0.5 + + # Do not compress assets + config.assets.compress = false + + # Expands the lines which load the assets + config.assets.debug = true +end diff --git a/dibs-web/config/environments/production.rb b/dibs-web/config/environments/production.rb new file mode 100644 index 0000000..9fb3183 --- /dev/null +++ b/dibs-web/config/environments/production.rb @@ -0,0 +1,67 @@ +Dibs::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false + + # Compress JavaScripts and CSS + config.assets.compress = true + + # Don't fallback to assets pipeline if a precompiled asset is missed + config.assets.compile = false + + # Generate digests for assets URLs + config.assets.digest = true + + # Defaults to nil and saved in location specified by config.assets.prefix + # config.assets.manifest = YOUR_PATH + + # Specifies the header that your server uses for sending files + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Prepend all log lines with the following tags + # config.log_tags = [ :subdomain, :uuid ] + + # Use a different logger for distributed setups + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile += %w( search.js ) + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify + + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + # config.active_record.auto_explain_threshold_in_seconds = 0.5 +end diff --git a/dibs-web/config/environments/test.rb b/dibs-web/config/environments/test.rb new file mode 100644 index 0000000..e6b8932 --- /dev/null +++ b/dibs-web/config/environments/test.rb @@ -0,0 +1,37 @@ +Dibs::Application.configure do + # Settings specified here will take precedence over those in config/application.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Configure static asset server for tests with Cache-Control for performance + config.serve_static_assets = true + config.static_cache_control = "public, max-age=3600" + + # Log error messages when you accidentally call methods on nil + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Print deprecation notices to the stderr + config.active_support.deprecation = :stderr +end diff --git a/dibs-web/config/initializers/backtrace_silencers.rb b/dibs-web/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/dibs-web/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/dibs-web/config/initializers/inflections.rb b/dibs-web/config/initializers/inflections.rb new file mode 100644 index 0000000..5d8d9be --- /dev/null +++ b/dibs-web/config/initializers/inflections.rb @@ -0,0 +1,15 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format +# (all these examples are active by default): +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end +# +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/dibs-web/config/initializers/mime_types.rb b/dibs-web/config/initializers/mime_types.rb new file mode 100644 index 0000000..72aca7e --- /dev/null +++ b/dibs-web/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/dibs-web/config/initializers/secret_token.rb b/dibs-web/config/initializers/secret_token.rb new file mode 100644 index 0000000..d99b878 --- /dev/null +++ b/dibs-web/config/initializers/secret_token.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +Dibs::Application.config.secret_token = '7971db0f7470719db67c53a48ec8906f77b093334897b37d3c7de71298f18d1b4c92d56a8e158884f656ad4620f495abdef4f1a00b10498d8fde21a396c7171a' diff --git a/dibs-web/config/initializers/session_store.rb b/dibs-web/config/initializers/session_store.rb new file mode 100644 index 0000000..21ce5e6 --- /dev/null +++ b/dibs-web/config/initializers/session_store.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +Dibs::Application.config.session_store :cookie_store, :key => '_dibs_session' + +# Use the database for sessions instead of the cookie-based default, +# which shouldn't be used to store highly confidential information +# (create the session table with "rails generate session_migration") +# Dibs::Application.config.session_store :active_record_store diff --git a/dibs-web/config/initializers/wrap_parameters.rb b/dibs-web/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..da4fb07 --- /dev/null +++ b/dibs-web/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters :format => [:json] +end + +# Disable root element in JSON by default. +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end diff --git a/dibs-web/config/locales/en.yml b/dibs-web/config/locales/en.yml new file mode 100644 index 0000000..179c14c --- /dev/null +++ b/dibs-web/config/locales/en.yml @@ -0,0 +1,5 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + hello: "Hello world" diff --git a/dibs-web/config/routes.rb b/dibs-web/config/routes.rb new file mode 100644 index 0000000..5d0385e --- /dev/null +++ b/dibs-web/config/routes.rb @@ -0,0 +1,179 @@ +=begin + routes.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +Dibs::Application.routes.draw do + root :to => "sessions#new" + + get "sessions/new" => "sessions#new" + + resources :users + + get "jobs" => "jobs#list" + + get "projects" => "projects#projects" + get "projects/fileUpload" + + get "signup" => "users#new", :as => "signup" + + post "login" => "sessions#create" + get "logout" => "sessions#destroy", :as => "logout" + + + # For asynchronous call + + post "users/signup" + post "users/modify" + + post "sessions/login" + delete "sessions/logout" + + get "jobs/list/all/:distribution/:status/:lastID" => "jobs#listAll", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + get "jobs/list/user/:user/:distribution/:status/:lastID" => "jobs#listSearchUser", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + get "jobs/list/group/:group/:distribution/:status/:lastID" => "jobs#listSearchGroup", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + get "jobs/list/project/:project/:distribution/:status/:lastID" => "jobs#listSearchProject" , :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/, :project => /[0-9A-Za-z\-\.]+/ } + get "jobs/list/date/:date/:distribution/:status/:lastID" => "jobs#listSearchDate", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + + match "jobs/update" => "jobs#updateList", :format => "json" + match "jobs/log/:id" => "jobs#log" + match "jobs/log/:id/:line" => "jobs#log_more" + match "jobs/cancel/:id" => "jobs#cancelJob" + + + get "projects/queryDistribution" + match "projects/queryProject/:distribution" => "projects#queryProject", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + post "projects/binaryFileUpload" + + # projects + match "projects/queryRunningProjectsInfoInDistribution/:distribution" => "projects#queryRunningProjectsInfoInDistribution", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + match "projects/queryProjectsInfoInDistribution/:distribution" => "projects#queryProjectsInfoInDistribution", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + match "projects/queryProjectsInDistribution/:distribution" => "projects#queryProjectsInDistribution" , :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + post "projects/buildProject" + + # admin group + get "admin_group/queryAllGroup" + match "admin_group/queryGroupInfo/:groupName" => "admin_group#queryGroupInfo" + post "admin_group/addGroup" + post "admin_group/removeGroup" + post "admin_group/modifyGroup" + + # admin user + get "admin_user/queryAllUser" + post "admin_user/removeUser" + post "admin_user/modifyUser" + + # admin server + get "admin_server/queryAllServer" + post "admin_server/addRemoteBuildServer" + post "admin_server/removeRemoteBuildServer" + post "admin_server/modifyRemoteBuildServer" + post "admin_server/addOsCategory" + post "admin_server/removeOsCategory" + post "admin_server/modifyOsCategory" + post "admin_server/addSupportedOS" + post "admin_server/removeSupportedOS" + post "admin_server/modifySupportedOS" + post "admin_server/addServerInfo" + post "admin_server/removeServerInfo" + post "admin_server/modifyServerInfo" + + # admin project + get "admin_project/queryAllProject" + match "admin_project/queryProjectsInDistributionForAdmin/:distribution" => "admin_project#queryProjectsInDistributionForAdmin", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + post "admin_project/addProject" + post "admin_project/removeProject" + post "admin_project/modifyProject" + + # admin distribution + get "admin_distribution/queryAllDistribution" + match "admin_distribution/queryDistributionInfo/:distribution" => "admin_distribution#queryDistributionInfo", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } + post "admin_distribution/addDistribution" + post "admin_distribution/removeDistribution" + post "admin_distribution/modifyDistribution" + + post "admin_distribution/fullBuildDistribution" + + get "admin/queryAllOS" + get "admin/queryAllOSCategory" + + # The priority is based upon order of creation: + # first created -> highest priority. + + # Sample of regular route: + # match 'products/:id' => 'catalog#view' + # Keep in mind you can assign values other than :controller and :action + + # Sample of named route: + # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase + # This route can be invoked with purchase_url(:id => product.id) + + # Sample resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Sample resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Sample resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Sample resource route with more complex sub-resources + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', :on => :collection + # end + # end + + # Sample resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + # root :to => 'welcome#index' + + # See how all your routes lay out with "rake routes" + + # This is a legacy wild controller route that's not recommended for RESTful applications. + # Note: This route will make all actions in every controller accessible via GET requests. + # match ':controller(/:action(/:id))(.:format)' +end diff --git a/dibs-web/db/schema.rb b/dibs-web/db/schema.rb new file mode 100644 index 0000000..f0ab07e --- /dev/null +++ b/dibs-web/db/schema.rb @@ -0,0 +1,76 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended to check this file into your version control system. + +ActiveRecord::Schema.define(:version => 20121024015858) do + + create_table "distributions", :force => true do |t| + t.string "name" + t.string "pkgsvr_url" + t.string "pkgsvr_addr" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "group_rights", :force => true do |t| + t.integer "group_id" + t.integer "project_id" + t.string "build" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "groups", :force => true do |t| + t.string "group_name" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "jobs", :force => true do |t| + t.string "job_id", :null => false + t.string "project_name" + t.string "distribution" + t.string "job_attribute" + t.string "os" + t.string "status" + t.integer "user_id" + t.string "parent_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "projects", :force => true do |t| + t.string "project_name" + t.string "distribution_name" + t.string "project_type" + t.string "os_list" + t.string "password" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "supported_os", :force => true do |t| + t.string "name" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "users", :force => true do |t| + t.string "email" + t.string "user_name" + t.string "password_hash" + t.string "password_salt" + t.integer "group_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + +end diff --git a/dibs-web/db/seeds.rb b/dibs-web/db/seeds.rb new file mode 100644 index 0000000..d34dfa0 --- /dev/null +++ b/dibs-web/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) +# Mayor.create(:name => 'Emanuel', :city => cities.first) diff --git a/dibs-web/doc/README_FOR_APP b/dibs-web/doc/README_FOR_APP new file mode 100644 index 0000000..fe41f5c --- /dev/null +++ b/dibs-web/doc/README_FOR_APP @@ -0,0 +1,2 @@ +Use this README file to introduce your application and point to useful places in the API for learning more. +Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. diff --git a/dibs-web/public/.project b/dibs-web/public/.project new file mode 100644 index 0000000..acb2d68 --- /dev/null +++ b/dibs-web/public/.project @@ -0,0 +1,57 @@ + + + dibs + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + json.validation.builder + + + + + org.tizen.web.jslint.nature.JSLintBuilder + + + + + org.tizen.web.css.nature.CSSBuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.tizen.web.project.builder.WebBuilder + + + usedLibraryType + jQueryMobile + + + + + + json.validation.nature + org.tizen.web.jslint.nature.JSLintNature + org.tizen.web.css.nature.CSSNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.tizen.web.project.builder.WebNature + + diff --git a/dibs-web/public/404.html b/dibs-web/public/404.html new file mode 100644 index 0000000..9a48320 --- /dev/null +++ b/dibs-web/public/404.html @@ -0,0 +1,26 @@ + + + + The page you were looking for doesn't exist (404) + + + + + +
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+ + diff --git a/dibs-web/public/422.html b/dibs-web/public/422.html new file mode 100644 index 0000000..83660ab --- /dev/null +++ b/dibs-web/public/422.html @@ -0,0 +1,26 @@ + + + + The change you wanted was rejected (422) + + + + + +
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+ + diff --git a/dibs-web/public/500.html b/dibs-web/public/500.html new file mode 100644 index 0000000..f3648a0 --- /dev/null +++ b/dibs-web/public/500.html @@ -0,0 +1,25 @@ + + + + We're sorry, but something went wrong (500) + + + + + +
+

We're sorry, but something went wrong.

+
+ + diff --git a/dibs-web/public/config.xml b/dibs-web/public/config.xml new file mode 100644 index 0000000..4ff99b6 --- /dev/null +++ b/dibs-web/public/config.xml @@ -0,0 +1,7 @@ + + + + + + test + diff --git a/dibs-web/public/favicon.ico b/dibs-web/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/dibs-web/public/index.html b/dibs-web/public/index.html new file mode 100644 index 0000000..e132087 --- /dev/null +++ b/dibs-web/public/index.html @@ -0,0 +1,1017 @@ + + + + + + DIBS 2.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+

Welcome to DIBS

+
    +
  • This system is support to build project. +
+
+ +
+
    +
+
+
+
+ +
+
+

Log in

+
+
+
+ + + + +
+
+ Cancel + Log in +
+
+
+
+ +
+
+

Sign up

+
+
+
+ + + + + + + + +
+
+
+ Cancel + Sign up +
+
+

+

+
+
+ +
+
+

+
+
+
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+
+ +
+
+
+
+ + + + + + + + + +
+
+
+
+
+
+ +
+
    +
+
+
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+
+
+ +
+
+
+

Git project

+
+ Build + Resolve +
+
+ +
+
+
+
+

Binary project

+
+ +
+
+
+ +
+ +
+
    +
+
+
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + + + + + + + + + + +
+ +
+
+
+ +
+ + Search + +
    +
+
+
+ + Search +
+
+ +
    +
+
+ + +
+ +
+
    +
+
+
+
+ +
+ +
+
+ + +
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+

User information

+
+ +
+
+
+ +
+
    +
+
+
+
+ +
+
+

Modify User

+
+
+
+ + +
+ + +
+
+ +
+ +
+
+
+
+
+ Save +
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+

Group information

+ +
+ +
+
+
+ +
+
    +
+
+
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+

Server information

+ +
+

Server info

+
    +
+
+ +
+

Supported OS

+
    +
+
+ +
+

Remote build server

+
    +
+
+
+
+
    +
+
+
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+

Project information

+
+
+ +
+
+
+
+
+

Git project

+ +
+ +
+
+
+
+

Binary project

+ + +
+
+
+
+
+ +
+
    +
+
+
+
+ +
+
+ Home +

DIBS 2.0

+
+
+
+ +
+
+

Distribution information

+
+
+ +
+ +
+

Package server url

+

+
+
+

Package server address

+

+
+
+

Status

+

+
+
+

Description

+

+
+
+

Sync package server

+
+
+
+
+ +
+
+ +
+
    +
+
+
+
+ +
+
+

Add Distribution

+
+
+
+ + +
+ + +
+ + +
+ + +
+ + +
+
+

Sync package server

+ + + + + + +
+
+
+
+ Save +
+
+ +
+
+

Modofy Distribution

+
+
+
+ + +
+ + +
+ + +
+ + +
+
+

Sync package server

+ + + + + + +
+
+
+
+ Save +
+
+ +
+
+

Add Git Project

+
+
+
+ + +
+ + +
+ + +
+ + +
+
+
+
+
+
+
+
+
+ Save +
+
+ +
+
+

Add Binary Project

+
+
+
+ + +
+ + +
+ + +
+
+
+
+
+
+
+
+ Save +
+
+ +
+
+

Modify Project

+
+
+
+ +
+ + +
+
+ +
+ +
+
+ + +
+ + +
+
+
+
+
+
+
+
+ Save +
+
+ +
+
+

Modify Project

+
+
+
+ +
+ + +
+
+ +
+ +
+
+ + +
+ + +
+ + +
+
+
+
+
+
+
+
+
+ Save +
+
+ +
+
+

Add Group

+
+
+
+ + +
+
+ +
+ +
+
+ + +
+
+
+
+
+
+
+
+
+ Save +
+
+ +
+
+

modify Group

+
+
+
+ + + +
+
+ +
+ +
+
+ + +
+
+
+
+
+
+
+
+
+ Save +
+
+ +
+
+

Add remote build server

+
+
+
+ + +
+ + +
+
+
+ Save +
+
+ +
+

Modify server

+
+
+
+ +
+ + +
+ + +
+
+
+ Save + Delete +
+
+ +
+
+

User information

+
+
+
+ + +
+ + +
+ + +
+ + +
+
+
+ Save +
+
+ +
+
+

Add supported os

+
+
+
+ + +
+
+ +
+ +
+
+
+
+ Save +
+
+ +
+
+

Modify supported os

+
+
+
+ + + +
+
+ +
+ +
+
+
+
+ Remove + Save +
+
+ +
+
+

Add os category

+
+
+
+ + +
+
+
+ Save +
+
+ +
+
+

Add os category

+
+
+
+
+ +
+ +
+
+
+
+ Delete +
+
+ +
+

Add server config

+
+
+
+ + +
+ + +
+
+
+ Save +
+
+ +
+

Modify server config

+
+
+
+ + +
+ + +
+
+
+ Save + Delete +
+
+ + + + + diff --git a/dibs-web/public/javascripts/admin-distribution-add.js b/dibs-web/public/javascripts/admin-distribution-add.js new file mode 100644 index 0000000..f648638 --- /dev/null +++ b/dibs-web/public/javascripts/admin-distribution-add.js @@ -0,0 +1,62 @@ +/* + admin-distribution-add.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminDistributionAdd() { + var changeInfoList = []; + var changeInfoItem; + var name = document.getElementById("adminDistributionAddPopup-DistirubtionName").value; + var url = document.getElementById("adminDistributionAddPopup-PackageServerUrl").value; + var address = document.getElementById("adminDistributionAddPopup-PackageServerAddress").value; + var description = document.getElementById("adminDistributionAddPopup-DistributionDescription").value; + var distStatus = $("#adminDistributionAddPopup-DistributionStatus option:selected").val(); + + var sync_pkg_svr_url = document.getElementById("adminDistributionAddPopup-SyncPackageServer-Url").value; + var sync_pkg_svr_period = document.getElementById("adminDistributionAddPopup-SyncPackageServer-period").value; + var sync_pkg_svr_description = document.getElementById("adminDistributionAddPopup-SyncPackageServer-Description").value; + + if(name == "" || url == "" || address == ""){ + alert("You must input full data"); + return; + } + + changeInfoItem = {"DistributionName":name, "URL":url, "Address":address, "DistStatus":distStatus, "Description":description, "SyncPkgSvrUrl":sync_pkg_svr_url, "SyncPkgSvrPeriod":sync_pkg_svr_period, "SyncPkgSvrDescription":sync_pkg_svr_description}; + changeInfoList.push(changeInfoItem); + + addDistribution(changeInfoList, function () { + document.getElementById("adminDistributionAddPopup-DistirubtionName").value = ""; + document.getElementById("adminDistributionAddPopup-PackageServerUrl").value = ""; + document.getElementById("adminDistributionAddPopup-PackageServerAddress").value = ""; + document.getElementById("adminDistributionAddPopup-DistributionDescription").value = ""; + document.getElementById("adminDistributionAddPopup-SyncPackageServer-Url").value = ""; + document.getElementById("adminDistributionAddPopup-SyncPackageServer-period").value = ""; + document.getElementById("adminDistributionAddPopup-SyncPackageServer-Description").value = ""; + + $.mobile.changePage("#adminDistribution"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-distribution-modify.js b/dibs-web/public/javascripts/admin-distribution-modify.js new file mode 100644 index 0000000..5c5c293 --- /dev/null +++ b/dibs-web/public/javascripts/admin-distribution-modify.js @@ -0,0 +1,110 @@ +/* + admin-distribution-modify.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminDistributionModifyPopupInit() { + var distName = $("#adminDistributionSelect option:selected").val(); + var packageServerUrl = document.getElementById("adminDistribution:packageServerUrl").innerHTML; + var packageServeraddress = document.getElementById("adminDistribution:packageServerAddress").innerHTML; + var serverStatusText = document.getElementById("adminDistribution:distributionStatus").innerHTML; + var serverDescription = document.getElementById("adminDistribution:distributionDescription").innerHTML; + + var syncPkgSvrUrl = document.getElementById("adminDistribution-SyncPackageServer-Url").innerHTML; + var syncPkgSvrPeriod = document.getElementById("adminDistribution-SyncPackageServer-period").innerHTML; + var syncPkgSvrDescription = document.getElementById("adminDistribution-SyncPackageServer-Description").innerHTML; + + if (syncPkgSvrUrl) { + syncPkgSvrUrl = syncPkgSvrUrl.replace("Package server url : ", ""); + } else { + syncPkgSvrUrl = "" + } + + if (syncPkgSvrPeriod) { + syncPkgSvrPeriod = syncPkgSvrPeriod.replace("Period : ", ""); + } else { + syncPkgSvrPeriod = "" + } + if (syncPkgSvrDescription) { + syncPkgSvrDescription = syncPkgSvrDescription.replace("Description : ", ""); + } else { + syncPkgSvrDescription = "" + } + + document.getElementById('adminDistributionModifyPopup-PackageServerUrl').value = packageServerUrl; + document.getElementById('adminDistributionModifyPopup-PackageServerAddress').value = packageServeraddress; + document.getElementById('adminDistributionModifyPopup-Description').value = serverDescription; + document.getElementById('adminDistributionModifyPopup-SyncPackageServer-Url').value = syncPkgSvrUrl; + document.getElementById('adminDistributionModifyPopup-SyncPackageServer-Period').value = syncPkgSvrPeriod; + document.getElementById('adminDistributionModifyPopup-SyncPackageServer-Description').value = syncPkgSvrDescription; + + $("#adminDistributionModifyPopup-Status").empty(); + var option; + if(serverStatusText.toUpperCase() == "OPEN") { + option = ''; + } else { + option = ''; + } + $("#adminDistributionModifyPopup-Status").append(option); + + if(serverStatusText.toUpperCase() == "CLOSE") { + option = ''; + } else { + option = ''; + } + $("#adminDistributionModifyPopup-Status").append(option); + $("#adminDistributionModifyPopup-Status").selectmenu("refresh"); +} + +function adminDistributionModify() { + var changeInfoList = []; + var changeInfoItem; + var distName = $("#adminDistributionSelect option:selected").val(); + var url = document.getElementById("adminDistributionModifyPopup-PackageServerUrl").value; + var address = document.getElementById("adminDistributionModifyPopup-PackageServerAddress").value; + var description = document.getElementById("adminDistributionModifyPopup-Description").value; + var distStatus = $("#adminDistributionModifyPopup-Status option:selected").val(); + var syncPkgSvrUrl = document.getElementById("adminDistributionModifyPopup-SyncPackageServer-Url").value; + var syncPkgSvrPeriod = document.getElementById("adminDistributionModifyPopup-SyncPackageServer-Period").value; + var syncPkgSvrDescription = document.getElementById("adminDistributionModifyPopup-SyncPackageServer-Description").value; + + if(distName == "" || url == "" || address == ""){ + alert("You must input full data"); + return; + } + + if(distStatus == "") { + distStatus = "OPEN"; + } + + changeInfoItem = {"DistributionName":distName, "URL":url, "Address":address, "DistStatus":distStatus, "Description":description, "SyncPkgSvrUrl":syncPkgSvrUrl, "SyncPkgSvrPeriod":syncPkgSvrPeriod, "SyncPkgSvrDescription":syncPkgSvrDescription}; + changeInfoList.push(changeInfoItem); + + modifyDistribution( changeInfoList, function () { + $.mobile.changePage("#adminDistribution"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-distribution.js b/dibs-web/public/javascripts/admin-distribution.js new file mode 100644 index 0000000..12e112b --- /dev/null +++ b/dibs-web/public/javascripts/admin-distribution.js @@ -0,0 +1,130 @@ +/* + admin-distribution.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminDistributionInit() { + queryAllDistribution( function (xml) { + var oldDistName = $("#adminDistributionSelect option:selected").val(); + var find = false; + var distributionList = $(xml).find("Data").find("DistributionName"); + + // remove old select options + $("#adminDistributionSelect").empty(); + + distributionList.each(function(){ + var name = $(this).text(); + + if( oldDistName == name ) { + $("#adminDistributionSelect").append(""); + find = true; + + } else { + $("#adminDistributionSelect").append(""); + } + }); + + /* default distribution selection */ + if(!find) { + $("#adminDistributionSelect option:eq(0)").attr("selected", "selected"); + } + + $("#adminDistributionSelect").selectmenu('refresh'); + + // set distribution info + adminDistributionSetInfo(); + }); +} + +function adminDistributionSetInfo() { + var distName = $("#adminDistributionSelect option:selected").val(); + + queryDistributionInfo( distName, function (xml) { + var data = $(xml).find("Data").find("DistributionInfo"); + var syncPackageServer = $(xml).find("Data").find("SyncPackageServer"); + var name = data.find("DistributionName").text(); + var url = data.find("PackageServerUrl").text(); + var address = data.find("PackageServerAddress").text(); + var distStatus = data.find("Status").text(); + var distDescription = data.find("Description").text(); + + $("#adminDistribution\\:packageServerUrl").text(url); + $("#adminDistribution\\:packageServerAddress").text(address); + $("#adminDistribution\\:distributionStatus").text(distStatus); + $("#adminDistribution\\:distributionDescription").text(distDescription); + + adminDistributionInitSyncPackageServer(syncPackageServer); + }); +} + +function adminDistributionRemove() { + var changeInfoList = []; + var changeInfoItem; + var distName = $("#adminDistributionSelect option:selected").val(); + + changeInfoItem = {"DistributionName":distName}; + changeInfoList.push(changeInfoItem); + + var r=confirm("Distribution ["+distName+"] will be removed!!!"); + if (r==false) + { + return; + } + + removeDistribution( changeInfoList, function (xml) { + $.mobile.changePage("#adminDistribution"); + }); +} + +function adminDistributionInitSyncPackageServer(serverInfo){ + $("#adminDistribution-SyncPackageServer").empty(); + + var info = '

Package server url : '+serverInfo.find("Url").text()+'

'; + info += '

Period : '+serverInfo.find("Period").text()+'

'; + info += '

Description : '+serverInfo.find("Description").text()+'

'; + + $("#adminDistribution-SyncPackageServer").append(info); +} + +function adminDistributionFullBuild() { + var changeInfoList = []; + var changeInfoItem; + var distName = $("#adminDistributionSelect option:selected").val(); + + changeInfoItem = {"DistributionName":distName}; + changeInfoList.push(changeInfoItem); + + var r=confirm("Distribution ["+distName+"] fullbuild will be started!!! it takes several time"); + if (r==false) + { + return; + } + + fullBuildDistribution( changeInfoList, function (xml) { + $.mobile.changePage("#adminDistribution"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-group-add.js b/dibs-web/public/javascripts/admin-group-add.js new file mode 100644 index 0000000..60c7a16 --- /dev/null +++ b/dibs-web/public/javascripts/admin-group-add.js @@ -0,0 +1,101 @@ +/* + admin-group-add.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminGroupAddInit() { + document.getElementById('adminGroupAddPopup-Name').value = ""; + document.getElementById('adminGroupAddPopup-Description').value = ""; + + queryAllProject( function(xml) { + var fullProjectList = $(xml).find("Data").find("Project"); + + adminGroupAddGenerateProjectSelect(fullProjectList); + }); +} + +function adminGroupAddGenerateProjectSelect(projectList) { + fieldset = document.getElementById('popup:addProjectCheckbox'); + + /* remove all table rows */ + while(fieldset.hasChildNodes()) + { + fieldset.removeChild(fieldset.firstChild); + } + + legend = document.createElement('legend'); + legend.innerHTML = "Project list"; + fieldset.appendChild(legend); + + projectList.each(function(){ + var projectName = $(this).find("Name").text(); + var projectId = $(this).find("Id").text(); + var projectDistName = $(this).find("DistName").text(); + + var input = document.createElement('input'); + input.type = 'checkbox'; + input.id = 'popup:addGroupProjectCheckbox:'+projectId; + input.name = 'popup:addGroupProjectCheckbox'; + input.value = projectName; + + var label = document.createElement('label'); + label.setAttribute('for', 'popup:addGroupProjectCheckbox:'+projectId); + label.innerHTML = projectName + "[" + projectDistName + "]"; + + fieldset.appendChild(input); + fieldset.appendChild(label); + }); + + $("[name='popup\\:addGroupProjectCheckbox']").checkboxradio(); +} + +function adminGroupAddGroup() { + var selectArray = document.getElementsByName('popup:addGroupProjectCheckbox'); + var groupName = document.getElementById('adminGroupAddPopup-Name').value; + var adminFlag = $("#adminGroupAddPopup-Admin option:selected").val(); + var description = document.getElementById('adminGroupAddPopup-Description').value; + var selectProjectIdList = ""; + var changeInfoList = []; + + for(var i = 0; i < selectArray.length; i++) { + if (selectArray[i].checked == true) { + var projectId = selectArray[i].id.split(":")[2]; + selectProjectIdList = selectProjectIdList + "," + projectId; + } + } + + if(selectProjectIdList.length > 0) { + selectProjectIdList = selectProjectIdList.substring(1,selectProjectIdList.length); + } + + changeItem = {"GroupName" : groupName, "AdminFlag":adminFlag, "Description":description, "ProjectList" : selectProjectIdList}; + changeInfoList.push(changeItem); + + addGroup(changeInfoList, function() { + $.mobile.changePage("#adminGroup"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-group-modify.js b/dibs-web/public/javascripts/admin-group-modify.js new file mode 100644 index 0000000..17ed56e --- /dev/null +++ b/dibs-web/public/javascripts/admin-group-modify.js @@ -0,0 +1,129 @@ +/* + admin-group-modify.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminGroupModifyInit() { + var index = localStorage.groupTableIndex; + var groupName = document.getElementById("groupTableName:"+index).innerHTML; + var description = document.getElementById("groupTableDescription:"+index).innerHTML; + var adminFlagText = document.getElementById("groupTableAdminFlag:"+index).innerHTML; + + document.getElementById('adminGroupModifyPopup-Name').value = groupName; + document.getElementById('adminGroupModifyPopup-NewName').value = groupName; + document.getElementById('adminGroupModifyPopup-Description').value = description; + $("#adminGroupModifyPopup-Admin").empty(); + var option; + if(adminFlagText.toUpperCase() == "TRUE") { + option = ''; + } else { + option = ''; + } + $("#adminGroupModifyPopup-Admin").append(option); + + if(adminFlagText.toUpperCase() == "FALSE") { + option = ''; + } else { + option = ''; + } + $("#adminGroupModifyPopup-Admin").append(option); + $("#adminGroupModifyPopup-Admin").selectmenu("refresh"); + + queryGroupInfo(groupName, function(xml) { + var fullProjectList = $(xml).find("Data").find("Project"); + var projectIdList = $(xml).find("Data").find("Group").find("ProjectList").text().split(","); + + adminGroupModifyGenerateProjectSelect(fullProjectList, projectIdList); + }); +} + +function adminGroupModifyGenerateProjectSelect(fullProjectList, projectIdList) { + fieldset = document.getElementById('popup:modifyProjectSelect'); + /* remove all table rows */ + while(fieldset.hasChildNodes()) + { + fieldset.removeChild(fieldset.firstChild); + } + + legend = document.createElement('legend'); + legend.innerHTML = "Project list"; + fieldset.appendChild(legend); + + fullProjectList.each(function(){ + var projectName = $(this).find("Name").text(); + var projectId = $(this).find("Id").text(); + var projectDistName = $(this).find("DistName").text(); + + var input = document.createElement('input'); + input.type = 'checkbox'; + input.id = 'popup:modifyProjectCheckbox:'+projectId; + input.name = 'popup:modifyProjectCheckbox'; + input.value = projectName; + + if(contains(projectIdList, projectId)) + { + input.setAttribute('checked', 'checked'); + } + + var label = document.createElement('label'); + label.setAttribute('for', 'popup:modifyProjectCheckbox:'+projectId); + label.innerHTML = projectName + "[" + projectDistName + "]"; + + fieldset.appendChild(input); + fieldset.appendChild(label); + }); + + $("[name='popup\\:modifyProjectCheckbox']").checkboxradio(); +} + +function adminGroupModifyGroup() { + var selectArray = document.getElementsByName('popup:modifyProjectCheckbox'); + var oldGroupName = document.getElementById('adminGroupModifyPopup-Name').value; + var groupName = document.getElementById('adminGroupModifyPopup-NewName').value; + var description = document.getElementById('adminGroupModifyPopup-Description').value; + var adminFlag = $("#adminGroupModifyPopup-Admin option:selected").val(); + var selectProjectIdList = ""; + var changeInfoList = []; + + for(var i = 0; i < selectArray.length; i++) { + if (selectArray[i].checked == true) { + var projectId = selectArray[i].id.split(":")[2]; + selectProjectIdList = selectProjectIdList + "," + projectId; + } + } + + if(selectProjectIdList.length > 0) { + selectProjectIdList = selectProjectIdList.substring(1,selectProjectIdList.length); + } + + changeItem = {"GroupName" : oldGroupName, "NewGroupName":groupName, "AdminFlag":adminFlag, "Description":description, "ProjectList" : selectProjectIdList}; + changeInfoList.push(changeItem); + + changeGroup(changeInfoList, function() { + $.mobile.changePage("#adminGroup"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-group.js b/dibs-web/public/javascripts/admin-group.js new file mode 100644 index 0000000..6f2104b --- /dev/null +++ b/dibs-web/public/javascripts/admin-group.js @@ -0,0 +1,165 @@ +/* + admin-group.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminGroupInit() { + adminGroupInitTable(); + + queryAllGroup( function(xml) { + var header = $(xml).find("Header"); + var groupList = $(xml).find("Data").find("Group"); + + adminGroupFillTableInfo(groupList); + }); +} + +function adminGroupInitTable() { + var groupTable = document.getElementById("groupTable"); + + /* remove all table rows */ + while(groupTable.hasChildNodes()) + { + groupTable.removeChild(groupTable.firstChild); + } +} + +function adminGroupFillTableInfo(groupList) { + var groupTable = document.getElementById("groupTable"); + + /* remove all table rows */ + while(groupTable.hasChildNodes()) + { + groupTable.removeChild(groupTable.firstChild); + } + + /* create table header */ + var row = groupTable.insertRow(-1); + var tableHeader = " Group name Project list Admin Description Modify Delete "; + + $("#groupTable").append(tableHeader); + + var index = 2; + + groupList.each(function(){ + var row = groupTable.insertRow(-1); + var cell; + var groupName = $(this).find("GroupName").text(); + var adminFlag = $(this).find("AdminFlag").text(); + var description = $(this).find("Description").text(); + var projectList = $(this).find("AccessableProject"); + + row.setAttribute('id', 'table:'+index); + + cell = row.insertCell(-1); + cell.setAttribute('id', 'groupTableName:'+index); + cell.innerHTML = groupName + + cell = row.insertCell(-1); + div = adminGroupGenerateProjectListCell(projectList); + cell.appendChild(div); + + cell = row.insertCell(-1); + cell.setAttribute('id', 'groupTableAdminFlag:'+index); + cell.innerHTML = adminFlag; + + cell = row.insertCell(-1); + cell.setAttribute('id', 'groupTableDescription:'+index); + cell.innerHTML = description; + + cell = row.insertCell(-1); + var button = document.createElement('a'); + button.setAttribute('href','#adminGroupModifyPopup'); + button.setAttribute('data-role','button'); + button.setAttribute('data-rel','dialog'); + button.setAttribute('onClick','adminGroupModifyPopupSetup(\"'+index+'\")'); + button.setAttribute('class','groupTableCellButton'); + button.innerHTML = " " + cell.appendChild(button); + + cell = row.insertCell(-1); + var button = document.createElement('input'); + button.setAttribute('type','button'); + button.setAttribute('onClick','adminGroupRemoveGroup('+index+')'); + button.setAttribute('class','groupTableCellButton'); + cell.appendChild(button); + + index = index + 1; + }); + + $(".groupProjectList").collapsible(); + $(".groupTableCellButton").button(); +} + +function adminGroupModifyPopupSetup(index) { + localStorage.groupTableIndex = index; +} + +function adminGroupGenerateProjectListCell(projectList) { + var div = document.createElement('div'); + div.setAttribute('data-role', 'collapsible'); + div.setAttribute('data-content-theme', 'b'); + div.setAttribute('class', 'groupProjectList'); + div.setAttribute('style', 'text-align: left'); + + var header = document.createElement('h3'); + header.innerHTML = "Project list"; + div.appendChild(header); + + var ul = document.createElement('ul'); + + projectList.each(function(){ + var projectName = $(this).find("ProjectName").text(); + var projectDistName = $(this).find("ProjectDistribution").text(); + var item = document.createElement('li'); + + item.innerHTML = projectName+"["+projectDistName+"]"; + ul.appendChild(item); + }); + + div.appendChild(ul); + return div; +} + +function adminGroupRemoveGroup(index) { + var groupName = document.getElementById("groupTableName:"+index).innerHTML; + + var r=confirm("User ["+groupName+"] will be removed!!!"); + if (r==false) + { + return; + } + + var changeInfoList = []; + var changeInfoItem; + changeInfoItem = {"GroupName":groupName}; + changeInfoList.push(changeInfoItem); + + removeGroup(changeInfoList, function() { + $.mobile.changePage("#adminGroup"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-project-add.js b/dibs-web/public/javascripts/admin-project-add.js new file mode 100644 index 0000000..7251408 --- /dev/null +++ b/dibs-web/public/javascripts/admin-project-add.js @@ -0,0 +1,177 @@ +/* + admin-project-add.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminProjectAddGitInit() { + document.getElementById("popup:addGitProjectName").value = ""; + document.getElementById("popup:addGitProjectPassword").value = ""; + document.getElementById("popup:addGitAddress").value = ""; + document.getElementById("popup:addGitBranch").value = ""; + + queryAllOS( function (xml) { + var osList = $(xml).find("Data").find("OsName"); + + fieldset = document.getElementById('popup:addGitProjectOs'); + /* remove all table rows */ + while(fieldset.hasChildNodes()) + { + fieldset.removeChild(fieldset.firstChild); + } + + legend = document.createElement('legend'); + legend.innerHTML = "Project os list"; + fieldset.appendChild(legend); + + osList.each(function(){ + var osName = $(this).text(); + + var input = document.createElement('input'); + input.type = 'checkbox'; + input.id = 'popup:addGitProjectOsCheckbox:'+osName; + input.name = 'popup:addGitProjectOsCheckbox'; + input.value = osName; + input.setAttribute('class', 'popup:addGitProjectOsCheckbox'); + input.setAttribute('checked', 'checked'); + + var label = document.createElement('label'); + label.setAttribute('for', 'popup:addGitProjectOsCheckbox:'+osName); + label.innerHTML = osName; + + fieldset.appendChild(input); + fieldset.appendChild(label); + }); + + $('.popup\\:addGitProjectOsCheckbox').checkboxradio(); + }); +} + +function adminProjectAddBinaryInit() { + document.getElementById("popup:addBinaryProjectName").value = ""; + document.getElementById("popup:addBinaryProjectPassword").value = ""; + document.getElementById("popup:addBinaryPackageName").value = ""; + + queryAllOS( function (xml) { + var osList = $(xml).find("Data").find("OsName"); + + fieldset = document.getElementById('popup:addBinaryProjectOs'); + /* remove all table rows */ + while(fieldset.hasChildNodes()) + { + fieldset.removeChild(fieldset.firstChild); + } + + legend = document.createElement('legend'); + legend.innerHTML = "Project os list"; + fieldset.appendChild(legend); + + osList.each(function(){ + var osName = $(this).text(); + + var input = document.createElement('input'); + input.type = 'checkbox'; + input.id = 'popup:addBinaryProjectOsCheckbox:'+osName; + input.name = 'popup:addBinaryProjectOsCheckbox'; + input.value = osName; + input.setAttribute('class', 'popup:addBinaryProjectOsCheckbox'); + input.setAttribute('checked', 'checked'); + + var label = document.createElement('label'); + label.setAttribute('for', 'popup:addBinaryProjectOsCheckbox:'+osName); + label.innerHTML = osName; + + fieldset.appendChild(input); + fieldset.appendChild(label); + }); + + $('.popup\\:addBinaryProjectOsCheckbox').checkboxradio(); + }); +} + +function adminProjectAddGitProject() { + var distName = $("#adminProjectDistributionSelect option:selected").val(); + var changeInfoList = []; + var changeInfoItem; + var type = "GIT"; + var name = document.getElementById("popup:addGitProjectName").value; + var password = document.getElementById("popup:addGitProjectPassword").value; + var address = document.getElementById("popup:addGitAddress").value; + var branch = document.getElementById("popup:addGitBranch").value; + var selectArray = document.getElementsByName('popup:addGitProjectOsCheckbox'); + var selectOsList = []; + + for(var i = 0; i < selectArray.length; i++) { + if (selectArray[i].checked == true) { + var osName = selectArray[i].id.split(":")[2]; + selectOsList.push(osName); + } + } + + + if(name == "" || password == "" || address == "" || branch == ""){ + alert("You must input full data(Project name, Git password, Git address, Branch)"); + return; + } + + changeInfoItem = {"Distribution":distName, "Name":name, "ProjectType":type, "ProjectPass":password, "Address":address, "Branch":branch, "OSNameList":selectOsList.toString()}; + changeInfoList.push(changeInfoItem); + + addProject(changeInfoList, function () { + $.mobile.changePage("#adminProject"); + }); +} + +function adminProjectAddBinaryProject() { + var distName = $("#adminProjectDistributionSelect option:selected").val(); + var changeInfoList = []; + var changeInfoItem; + var type = "BINARY"; + var name = document.getElementById("popup:addBinaryProjectName").value; + var password = document.getElementById("popup:addBinaryProjectPassword").value; + var pkgName = document.getElementById("popup:addBinaryPackageName").value; + var selectArray = document.getElementsByName('popup:addBinaryProjectOsCheckbox'); + var selectOsList = []; + + for(var i = 0; i < selectArray.length; i++) { + if (selectArray[i].checked == true) { + var osName = selectArray[i].id.split(":")[2]; + selectOsList.push(osName); + } + } + + if(name == "" || pkgName == ""){ + alert("You must input full data(Project name, Package name"); + return; + } + + changeInfoItem = {"Distribution":distName, "Name":name, "ProjectType":type, "ProjectPass":password, "PackageName":pkgName, "OSNameList":selectOsList.toString()}; + changeInfoList.push(changeInfoItem); + + addProject(changeInfoList, function () { + $.mobile.changePage("#adminProject"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-project-modify.js b/dibs-web/public/javascripts/admin-project-modify.js new file mode 100644 index 0000000..420d093 --- /dev/null +++ b/dibs-web/public/javascripts/admin-project-modify.js @@ -0,0 +1,209 @@ +/* + admin-project-modify.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminProjectModifyBinaryProjectInit() { + var projectName = localStorage.projectName; + var packageName = document.getElementById('modifyBinaryPackageName:'+projectName).innerHTML; + + document.getElementById('popup:modifyBinaryOldProjectName').value = projectName; + document.getElementById('popup:modifyBinaryNewProjectName').value = projectName; + document.getElementById('popup:modifyBinaryProjectPassword').value = ""; + document.getElementById('popup:modifyBinaryPackageName').value = packageName; + + queryAllOS( function (xml) { + var osList = $(xml).find("Data").find("OsName"); + var selectedOsList = []; + var projectName = localStorage.projectName; + + var osListElement = document.getElementById('adminBINARYProjectTableOsList:'+projectName); + for(var i = 0; i < osListElement.childNodes.length; i++) + { + selectedOsList.push(osListElement.childNodes[i].innerHTML); + } + + fieldset = document.getElementById('popup:modifyBinaryProjectOs'); + /* remove all table rows */ + while(fieldset.hasChildNodes()) + { + fieldset.removeChild(fieldset.firstChild); + } + + legend = document.createElement('legend'); + legend.innerHTML = "Project os list"; + fieldset.appendChild(legend); + + osList.each(function(){ + var osName = $(this).text(); + + var input = document.createElement('input'); + input.type = 'checkbox'; + input.id = 'popup:modifyBinaryProjectOs:'+osName; + input.name = 'popup:modifyBinaryProjectOs' + input.value = osName; + input.setAttribute('class', 'popup:modifyBinaryProjectOs'); + if(contains(selectedOsList, osName)) + { + input.setAttribute('checked', 'checked'); + } + + var label = document.createElement('label'); + label.setAttribute('for', 'popup:modifyBinaryProjectOs:'+osName); + label.innerHTML = osName; + + fieldset.appendChild(input); + fieldset.appendChild(label); + }); + + $('.popup\\:modifyBinaryProjectOs').checkboxradio(); + }); +} + +function adminProjectModifyGitProjectInit() { + var projectName = localStorage.projectName; + var projectAddress = document.getElementById('modifyGitProjectAddress:'+projectName).innerHTML; + var projectBranch = document.getElementById('modifyGitProjectBranch:'+projectName).innerHTML; + + document.getElementById('popup:modifyGitOldProjectName').value = projectName; + document.getElementById('popup:modifyGitNewProjectName').value = projectName; + document.getElementById('popup:modifyGitProjectPassword').value = ""; + document.getElementById('popup:modifyGitProjectAddress').value = projectAddress; + document.getElementById('popup:modifyGitProjectBranch').value = projectBranch; + + queryAllOS( function (xml) { + var osList = $(xml).find("Data").find("OsName"); + var selectedOsList = []; + var projectName = localStorage.projectName; + + var osListElement = document.getElementById('adminGITProjectTableOsList:'+projectName); + for(var i = 0; i < osListElement.childNodes.length; i++) + { + selectedOsList.push(osListElement.childNodes[i].innerHTML); + } + + fieldset = document.getElementById('popup:modifyGitProjectOs'); + /* remove all table rows */ + while(fieldset.hasChildNodes()) + { + fieldset.removeChild(fieldset.firstChild); + } + + legend = document.createElement('legend'); + legend.innerHTML = "Project os list"; + fieldset.appendChild(legend); + + osList.each(function(){ + var osName = $(this).text(); + + var input = document.createElement('input'); + input.type = 'checkbox'; + input.id = 'popup:modifyGitProjectOs:'+osName; + input.name = 'popup:modifyGitProjectOs' + input.value = osName; + input.setAttribute('class', 'popup:modifyGitProjectOs'); + if(contains(selectedOsList, osName)) + { + input.setAttribute('checked', 'checked'); + } + + var label = document.createElement('label'); + label.setAttribute('for', 'popup:modifyGitProjectOs:'+osName); + label.innerHTML = osName; + + fieldset.appendChild(input); + fieldset.appendChild(label); + }); + + $('.popup\\:modifyGitProjectOs').checkboxradio(); + }); +} + +function adminProjectModfyBinaryProject() { + var distName = $("#adminProjectDistributionSelect option:selected").val(); + var changeInfoList = []; + var changeInfoItem; + var oldProjectName = document.getElementById('popup:modifyBinaryOldProjectName').value; + var newProjectName = document.getElementById('popup:modifyBinaryNewProjectName').value; + var projectType = document.getElementById('popup:modifyBinaryProjectType').value; + var projectPassword = document.getElementById('popup:modifyBinaryProjectPassword').value; + var packageName = document.getElementById('popup:modifyBinaryPackageName').value; + var selectArray = document.getElementsByName('popup:modifyBinaryProjectOs'); + var selectOsList = []; + + for(var i = 0; i < selectArray.length; i++) { + if (selectArray[i].checked == true) { + var osName = selectArray[i].id.split(":")[2]; + selectOsList.push(osName); + } + } + + if(oldProjectName == "" || newProjectName == "" || projectPassword == "" || projectType == "" || packageName == ""){ + alert("You must input full data"); + return; + } + + changeInfoItem = {"Distribution":distName, "Name":oldProjectName, "NewProjectName":newProjectName, "ProjectType":projectType, "ProjectPass":projectPassword, "PackageName":packageName, "OSNameList":selectOsList.toString()}; + changeInfoList.push(changeInfoItem); + + modifyProject(changeInfoList, function () { + $.mobile.changePage("#adminProject"); + }); +} + +function adminProjectModfyGitProject() { + var distName = $("#adminProjectDistributionSelect option:selected").val(); + var changeInfoList = []; + var changeInfoItem; + var oldProjectName = document.getElementById('popup:modifyGitOldProjectName').value; + var newProjectName = document.getElementById('popup:modifyGitNewProjectName').value; + var projectType = document.getElementById('popup:modifyGitProjectType').value; + var projectPassword = document.getElementById('popup:modifyGitProjectPassword').value; + var projectAddress = document.getElementById('popup:modifyGitProjectAddress').value; + var projectBranch = document.getElementById('popup:modifyGitProjectBranch').value; + var selectArray = document.getElementsByName('popup:modifyGitProjectOs'); + var selectOsList = []; + + for(var i = 0; i < selectArray.length; i++) { + if (selectArray[i].checked == true) { + var osName = selectArray[i].id.split(":")[2]; + selectOsList.push(osName); + } + } + + if(oldProjectName == "" || newProjectName == "" || projectPassword == "" || projectType == "" || projectAddress == "" || projectBranch == ""){ + alert("You must input full data"); + return; + } + + changeInfoItem = {"Distribution":distName, "Name":oldProjectName, "NewProjectName":newProjectName, "ProjectType":projectType, "ProjectPass":projectPassword, "ProjectAddress":projectAddress, "ProjectBranch":projectBranch, "OSNameList":selectOsList.toString()}; + changeInfoList.push(changeInfoItem); + + modifyProject(changeInfoList, function () { + $.mobile.changePage("#adminProject"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-project.js b/dibs-web/public/javascripts/admin-project.js new file mode 100644 index 0000000..03e06b7 --- /dev/null +++ b/dibs-web/public/javascripts/admin-project.js @@ -0,0 +1,255 @@ +/* + admin-project.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminProjectInit() { + queryAllDistribution( function (xml) { + var oldDistName = $("#adminProjectDistributionSelect option:selected").val(); + var find = false; + var distributionList = $(xml).find("Data").find("DistributionName"); + + // remove old select options + $("#adminProjectDistributionSelect").empty(); + + distributionList.each(function(){ + var name = $(this).text(); + + if( oldDistName == name ) { + $("#adminProjectDistributionSelect").append(""); + find = true; + + } else { + $("#adminProjectDistributionSelect").append(""); + } + }); + + /* default distribution selection */ + if(!find) { + $("#adminProjectDistributionSelect option:eq(0)").attr("selected", "selected"); + } + + $("#adminProjectDistributionSelect").selectmenu('refresh'); + + // set project info + adminProjectSetProjectInfo(); + }); +} + +function adminProjectSetProjectInfo() { + var distName = $("#adminProjectDistributionSelect option:selected").val(); + + queryProjectsInDistributionForAdmin( distName, function (xml) { + var projectList = $(xml).find("Data").find("Project"); + + // update project info + adminProjectUpdateTable(projectList); + }); +} + +function popupModifyProject(projectName) { + localStorage.projectName = projectName; +} + +function adminProjectRemoveProject(projectType, projectName ) { + var distName = $("#adminProjectDistributionSelect option:selected").val(); + + var r=confirm("Project ["+projectName+"] is removed!!!"); + if (r==false) + { + return; + } + + var changeInfoList = []; + var changeInfoItem; + changeInfoItem = {"Distribution":distName, "ProjectType":projectType, "Name":projectName}; + changeInfoList.push(changeInfoItem); + + removeProject(changeInfoList, function () { + $.mobile.changePage("#adminProject"); + }); +} + +function adminProjectUpdateTable(projectList) { + /* project table */ + var projectTable = document.getElementById("adminProjectTable"); + + /* binary project table */ + var binaryProjectTable = document.getElementById("adminBinaryProjectTable"); + + /* remove all table rows */ + while(projectTable.hasChildNodes()) + { + projectTable.removeChild(projectTable.firstChild); + } + while(binaryProjectTable.hasChildNodes()) + { + binaryProjectTable.removeChild(binaryProjectTable.firstChild); + } + + // Project table header + var tableHeader = "ProjectGit reposBranchOS listModifyDelete"; + $("#adminProjectTable").append(tableHeader); + + // Binary project table header + var tableHeader = "ProjectPackage nameOS listModifyDelete"; + $("#adminBinaryProjectTable").append(tableHeader); + + var projectIdx = 1; + var binaryProjectIdx = 1; + // add project information + projectList.each(function(){ + var name = $(this).find("ProjectName").text(); + var type = $(this).find("Type").text(); + var osList = $(this).find("OS"); + + if(type.toUpperCase() == "GIT") + { + var row = projectTable.insertRow(-1); + var cell; + + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('id',"modifyGitProjectName:"+name); + cell.innerHTML = name; + + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('id',"modifyGitProjectAddress:"+name); + cell.innerHTML = $(this).find("GitRepos").text(); + + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('id',"modifyGitProjectBranch:"+name); + cell.innerHTML = $(this).find("GitBranch").text(); + + cell = row.insertCell(-1); + div = adminProjectApendOsCell(osList, name, "GIT"); + cell.appendChild(div); + + cell = row.insertCell(-1); + var button = document.createElement('a'); + button.setAttribute('href','#modifyGitProject'); + button.setAttribute('data-role','button'); + button.setAttribute('data-rel','dialog'); + button.setAttribute('data-mini','true'); + button.setAttribute('onClick','popupModifyProject(\"'+name+'\")'); + button.setAttribute('class','binaryProjectTableButton'); + button.innerHTML = " " + cell.appendChild(button); + + cell = row.insertCell(-1); + var button = document.createElement('input'); + button.setAttribute('type','button'); + button.setAttribute('id','button:git:'+projectIdx+':'+name); + button.setAttribute('data-mini','true'); + button.setAttribute('name',name); + button.setAttribute('class','binaryProjectTableButton'); + button.setAttribute('onClick','adminProjectRemoveProject(\"GIT\"'+',\"'+name+'\"'+')'); + cell.appendChild(button); + + projectIdx = projectIdx + 1; + } + else if (type.toUpperCase() == "BINARY") + { + var row = binaryProjectTable.insertRow(-1); + var cell; + + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('id',"modifyBinaryProjectName:"+name); + cell.innerHTML = name; + + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('id',"modifyBinaryPackageName:"+name); + cell.innerHTML = $(this).find("PackageName").text(); + + cell = row.insertCell(-1); + div = adminProjectApendOsCell(osList, name, "BINARY"); + cell.appendChild(div); + + cell = row.insertCell(-1); + var button = document.createElement('a'); + button.setAttribute('href','#modifyBinaryProject'); + button.setAttribute('data-role','button'); + button.setAttribute('data-inline','true'); + button.setAttribute('data-mini','true'); + button.setAttribute('data-rel','dialog'); + button.setAttribute('onClick','popupModifyProject(\"'+name+'\")'); + button.setAttribute('class','binaryProjectTableButton'); + cell.appendChild(button); + + cell = row.insertCell(-1); + var button = document.createElement('input'); + button.setAttribute('type','button'); + button.setAttribute('class','binaryProjectTableButton'); + button.setAttribute('data-mini','true'); + button.setAttribute('name',name); + button.setAttribute('onClick','adminProjectRemoveProject(\"BINARY\"'+',\"'+name+'\"'+')'); + cell.appendChild(button); + + binaryProjectIdx = binaryProjectIdx + 1; + } + else + alert("Unknown project type"); + + }); + + $(".binaryProjectTableButton").button(); + $(".groupProjectList").collapsible(); +} + +function adminProjectApendOsCell(osList, projectName, projectType) { + + var div = document.createElement('div'); + + div.setAttribute('data-role', 'collapsible'); + div.setAttribute('data-mini', 'true'); + div.setAttribute('data-content-theme', 'b'); + div.setAttribute('class', 'groupProjectList'); + + var header = document.createElement('h3'); + header.innerHTML = "OS list"; + div.appendChild(header); + + var ul = document.createElement('ul'); + ul.setAttribute('id', 'admin'+projectType+'ProjectTableOsList:'+projectName); + + // if osList does not exist then just return + if (osList != undefined) { + osList.each(function(){ + var item = document.createElement('li'); + item.innerHTML = $(this).text(); + ul.appendChild(item); + }); + } + + div.appendChild(ul); + return div; +} + + diff --git a/dibs-web/public/javascripts/admin-server-add.js b/dibs-web/public/javascripts/admin-server-add.js new file mode 100644 index 0000000..18a47d2 --- /dev/null +++ b/dibs-web/public/javascripts/admin-server-add.js @@ -0,0 +1,133 @@ +/* + admin-server-add.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminServerAddSupportedOsInit() { + // Remove select option + $('#adminServer-AddSupportedOs-OsCategory').empty(); + + queryAllOSCategory(function(xml){ + $(xml).find("Data").find("OsCategoryName").each(function(){ + var name = $(this).text(); + + $('#adminServer-AddSupportedOs-OsCategory').append(""); + + $('#adminServer-AddSupportedOs-OsCategory').selectmenu('refresh'); + }); + }); +} + +function adminServerAddRemoteBuildServer() { + var changeInfoList = []; + var changeInfoItem; + + var address = document.getElementById("adminServer-AddRemoteBuildServer-Address").value; + var description = document.getElementById("adminServer-AddRemoteBuildServer-Description").value; + + if(address == ""){ + alert("You must input server address"); + return; + } + + changeInfoItem = {"Address":address, "Description":description}; + changeInfoList.push(changeInfoItem); + + addRemoteBuildServer(changeInfoList, function () { + document.getElementById('adminServer-AddRemoteBuildServer-Address').value = ""; + document.getElementById('adminServer-AddRemoteBuildServer-Description').value = ""; + + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerAddSupportedOs() { + var changeInfoList = []; + var changeInfoItem; + + var osName = document.getElementById("adminServer-AddSupportedOs-OsName").value; + var osCategory = $("#adminServer-AddSupportedOs-OsCategory option:selected").val(); + + if(osName == ""){ + alert("You must input server address"); + return; + } + + changeInfoItem = {"Name":osName, "OsCategory":osCategory}; + changeInfoList.push(changeInfoItem); + + addSupportedOS(changeInfoList, function () { + document.getElementById('adminServer-AddSupportedOs-OsName').value = ""; + + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerAddOSCategory() { + var changeInfoList = []; + var changeInfoItem; + + var categoryName = document.getElementById("adminServer-AddOsCategory-Name").value; + + if(categoryName == ""){ + alert("You must input category name"); + return; + } + + changeInfoItem = {"Name":categoryName}; + changeInfoList.push(changeInfoItem); + + addOSCategory(changeInfoList, function () { + document.getElementById('adminServer-AddOsCategory-Name').value = ""; + + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerAddServerInfo() { + var property = document.getElementById('adminServer-addServerInfo-property').value; + var value = document.getElementById('adminServer-addServerInfo-value').value; + var changeInfoList = []; + var changeInfoItem; + + if(property == ""){ + alert("property is empty"); + return; + } + + if(value == ""){ + alert("value is empty"); + return; + } + + changeInfoItem = {"Property":property, "Value":value}; + changeInfoList.push(changeInfoItem); + + addServerInfo(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-server-modify.js b/dibs-web/public/javascripts/admin-server-modify.js new file mode 100644 index 0000000..28e9c97 --- /dev/null +++ b/dibs-web/public/javascripts/admin-server-modify.js @@ -0,0 +1,125 @@ +/* + admin-server-modify.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminServerModifyRemoteBuildServerInit() { + var serverAddress = localStorage.remoteBuildServerAddress; + var serverDescription = localStorage.remoteBuildServerDescription; + + document.getElementById('adminServer-modifyRemoteBuildServer-OldAddress').value = serverAddress; + document.getElementById('adminServer-modifyRemoteBuildServer-newAddress').value = serverAddress; + document.getElementById('adminServer-modifyRemoteBuildServer-description').value = serverDescription +} + +function adminServerModifyServerInfoInit(property, value) { + document.getElementById('adminServer-modifyServerInfo-property').value = property; + document.getElementById('adminServer-modifyServerInfo-value').value = value; +} + +function adminServerModifySupportedOSInit(osName, osCategory) { + // Remove select option + $('#adminServer-ModifySupportedOs-OsCategory').empty(); + + document.getElementById('adminServer-ModifySupportedOs-OldOsName').value = osName; + document.getElementById('adminServer-MoidfySupportedOs-OsName').value = osName; + + queryAllOSCategory( function(xml){ + $(xml).find("Data").find("OsCategoryName").each(function(){ + var name = $(this).text(); + var option = "" + + if(name == osCategory) { + option = '' + } else { + option = '' + } + + $('#adminServer-ModifySupportedOs-OsCategory').append(option); + $('#adminServer-ModifySupportedOs-OsCategory').selectmenu("refresh"); + }); + }); +} + +function adminServerModifyRemoteBuildServer() { + var changeInfoList = []; + var changeInfoItem; + var serverAddress = document.getElementById('adminServer-modifyRemoteBuildServer-OldAddress').value; + var newServerAddress = document.getElementById('adminServer-modifyRemoteBuildServer-newAddress').value; + var description = document.getElementById('adminServer-modifyRemoteBuildServer-description').value; + + if(serverAddress == ""){ + alert("server address is invalid"); + return; + } + + changeInfoItem = {"Address":serverAddress, "NewAddress":newServerAddress, "Description":description}; + changeInfoList.push(changeInfoItem); + + modifyRemoteBuildServer(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerModifySupportedOS() { + var changeInfoList = []; + var changeInfoItem; + var oldOsName = document.getElementById('adminServer-ModifySupportedOs-OldOsName').value; + var osName = document.getElementById('adminServer-MoidfySupportedOs-OsName').value; + var osCategory = $("#adminServer-ModifySupportedOs-OsCategory option:selected").val(); + + changeInfoItem = {"Name":oldOsName, "NewName":osName, "OsCategory":osCategory}; + changeInfoList.push(changeInfoItem); + + modifySupportedOS(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerModifyServerInfo() { + var property = document.getElementById('adminServer-modifyServerInfo-property').value; + var value = document.getElementById('adminServer-modifyServerInfo-value').value; + var changeInfoList = []; + var changeInfoItem; + + if(property == ""){ + alert("property is empty"); + return; + } + + if(value == ""){ + alert("value is empty"); + return; + } + + changeInfoItem = {"Property":property, "Value":value}; + changeInfoList.push(changeInfoItem); + + modifyServerInfo(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-server-remove.js b/dibs-web/public/javascripts/admin-server-remove.js new file mode 100644 index 0000000..db74a01 --- /dev/null +++ b/dibs-web/public/javascripts/admin-server-remove.js @@ -0,0 +1,116 @@ +/* + admin-server-remove.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminServerRemoveOSCategoryInit() { + // Remove select option + $('#adminServer-RemoveOSCategory-CategorySelect').empty(); + + queryAllOSCategory(function(xml){ + $(xml).find("Data").find("OsCategoryName").each(function(){ + var name = $(this).text(); + + $('#adminServer-RemoveOSCategory-CategorySelect').append(""); + + $('#adminServer-RemoveOSCategory-CategorySelect').selectmenu('refresh'); + }); + }); +} + +function adminServerRemoveOSCategory() { + var changeInfoList = []; + var changeInfoItem; + var osCategory = $("#adminServer-RemoveOSCategory-CategorySelect option:selected").val(); + + if(osCategory == ""){ + alert("Os category is invalid"); + return; + } + + changeInfoItem = {"Name":osCategory}; + changeInfoList.push(changeInfoItem); + + removeOSCategory(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerRemoveSupportedOS() { + var changeInfoList = []; + var changeInfoItem; + var oldOsName = document.getElementById('adminServer-ModifySupportedOs-OldOsName').value; + var osName = document.getElementById('adminServer-MoidfySupportedOs-OsName').value; + + if(oldOsName != osName ){ + alert("Remove command must be same to original os name"); + return; + } + + changeInfoItem = {"Name":osName}; + changeInfoList.push(changeInfoItem); + + removeSupportedOS(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerRemoveServerInfo() { + var property = document.getElementById('adminServer-modifyServerInfo-property').value; + var changeInfoList = []; + var changeInfoItem; + + if(property == ""){ + alert("property is empty"); + return; + } + + changeInfoItem = {"Property":property}; + changeInfoList.push(changeInfoItem); + + removeServerInfo(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + +function adminServerRemoveRemoteBuildServer() { + var changeInfoList = []; + var changeInfoItem; + var serverAddress = document.getElementById('adminServer-modifyRemoteBuildServer-OldAddress').value; + + if(serverAddress == ""){ + alert("server address is invalid"); + return; + } + + changeInfoItem = {"Address":serverAddress}; + changeInfoList.push(changeInfoItem); + + removeRemoteBuildServer(changeInfoList, function () { + $.mobile.changePage("#adminServer"); + }); +} + diff --git a/dibs-web/public/javascripts/admin-server.js b/dibs-web/public/javascripts/admin-server.js new file mode 100644 index 0000000..6aae3e9 --- /dev/null +++ b/dibs-web/public/javascripts/admin-server.js @@ -0,0 +1,109 @@ +/* + admin-server.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminServerInit() { + $('#adminServer-RemoteBuildServer').collapsible(); + + queryAllServer( function (xml) { + var serverConfig = $(xml).find("Data").find("ServerConfig"); + var buildServerList = $(xml).find("Data").find("RemoteBuildServer"); + var syncPackageServerList = $(xml).find("Data").find("SyncPackageServer"); + adminServerInitServerInfo(serverConfig); + adminServerRemoteInitRemoteBuildServer(buildServerList); + }); + + queryAllOS( function (xml) { + $("#adminServer-SupportedOS").empty(); + + $(xml).find("Data").find("OS").each(function(){ + var osName = $(this).find("OsName").text(); + var osCategory = $(this).find("OsCategory").text(); + + var li = '
  • '; + li += '

    OS category : '+osCategory+'

    '; + li += '
  • '; + + $("#adminServer-SupportedOS").append(li); + }); + + $("#adminServer-SupportedOS").listview('refresh'); + }); +} + +function adminServerInitServerInfo(serverConfig){ + $("#adminServer-ServerInfo").empty(); + + serverConfig.each(function(){ + var property = $(this).find("Property").text(); + var value = $(this).find("Value").text(); + + var li = '
  • '; + li += '
  • '; + $("#adminServer-ServerInfo").append(li); + }); + + $("#adminServer-ServerInfo").listview('refresh'); +} + +function adminServerRemoteInitRemoteBuildServer(serverList){ + $("#adminServer-RemoteBuildServer").empty(); + + serverList.each(function(){ + var address = $(this).find("Address").text(); + var description = $(this).find("Description").text(); + + var li = '
  • '; + li += '

    Description : '+$(this).find("Description").text()+'

    '; + li += '

    Runtime infomation

    '; + li += '

    Status: '+$(this).find("Status").text()+'

    '; + li += '

    Supported OS: '+$(this).find("SupportedOS").text()+'

    '; + li += '

    Max job count: '+$(this).find("MaxJobCount").text()+'

    '; + li += '

    Working job count: '+$(this).find("WorkingJobCount").text()+'

    '; + li += '

    Waiting job count: '+$(this).find("WaitingJobCount").text()+'

    '; + li += '
  • '; + + $("#adminServer-RemoteBuildServer").append(li); + }); + + $("#adminServer-RemoteBuildServer").listview('refresh'); +} + +function popupModifyRemoteBuildServerInfo(address, description) { + localStorage.remoteBuildServerAddress = address; + localStorage.remoteBuildServerDescription = description; +} + diff --git a/dibs-web/public/javascripts/admin-user-modify.js b/dibs-web/public/javascripts/admin-user-modify.js new file mode 100644 index 0000000..fd00e41 --- /dev/null +++ b/dibs-web/public/javascripts/admin-user-modify.js @@ -0,0 +1,71 @@ +/* + admin-user-modify.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminUserModifyPopupInit() { + var index = localStorage.userTableIndex; + var userName = document.getElementById("userTableName:"+index).innerHTML; + var email = document.getElementById("userTableEmail:"+index).innerHTML; + var group = document.getElementById("userTableGroup:"+index).innerHTML; + + document.getElementById('popup:modifyUserName').value = userName; + mailElement = document.getElementById('popup:modifyUserEmail'); + mailElement.value = email; + mailElement.setAttribute('disabled', 'disabled'); + + queryAllGroup( function(xml) { + var groupList = $(xml).find("Data").find("GroupName"); + + $("#popup\\:modifyUserGroup").empty(); + + groupList.each( function(){ + var groupName = $(this).text(); + if( groupName == group ) { + $("#popup\\:modifyUserGroup").append(""); + } else { + $("#popup\\:modifyUserGroup").append(""); + } + + $("#popup\\:modifyUserGroup").selectmenu('refresh'); + }); + }); +} + +function adminUserModifyPopupModify() { + var userName = document.getElementById("popup:modifyUserName").value; + var email = document.getElementById("popup:modifyUserEmail").value; + var groupName = $("#popup\\:modifyUserGroup option:selected").val(); + + var changeInfoList = []; + var changeInfoItem; + changeInfoItem = {"Type":"ModifyUser", "Email":email, "UserName":userName, "GroupName":groupName}; + changeInfoList.push(changeInfoItem); + + changeUser(changeInfoList, function () { + }); +} + diff --git a/dibs-web/public/javascripts/admin-user.js b/dibs-web/public/javascripts/admin-user.js new file mode 100644 index 0000000..73acf00 --- /dev/null +++ b/dibs-web/public/javascripts/admin-user.js @@ -0,0 +1,119 @@ +/* + admin-user.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function adminUserInit() { + var userTable = document.getElementById("adminUserTable"); + + /* remove all table rows */ + while(userTable.hasChildNodes()) + { + userTable.removeChild(userTable.firstChild); + } + + /* create table header */ + var tableHeader = "User nameEmailGroupModifyDelete"; + $("#adminUserTable").append(tableHeader); + + queryAllUser( function(xml) { + var userList = $(xml).find("Data").find("User"); + + adminUserFillTable(userList); + }); +} + +function adminUserFillTable(userList) { + var userTable = document.getElementById("adminUserTable"); + var index = 2; + + userList.each(function(idx){ + var row = userTable.insertRow(-1); + var cell; + var userName = $(this).find("Name").text(); + var groupName = $(this).find("GroupName").text(); + var email = $(this).find("Email").text(); + + row.setAttribute('id', 'userTable:'+index); + cell = row.insertCell(-1); + cell.setAttribute('id',"userTableName:"+index); + cell.innerHTML = userName; + + cell = row.insertCell(-1); + cell.setAttribute('id',"userTableEmail:"+index); + cell.innerHTML = email; + + cell = row.insertCell(-1); + cell.setAttribute('id',"userTableGroup:"+index); + cell.innerHTML = groupName; + + cell = row.insertCell(-1); + var button = document.createElement('a'); + button.setAttribute('href','#adminUserModifyPopup'); + button.setAttribute('data-role','button'); + button.setAttribute('data-rel','dialog'); + button.setAttribute('class','adminUserTableButton'); + button.setAttribute('onClick','adminUserModifyPopupSetup(\"'+index+'\")'); + button.innerHTML = " " + cell.appendChild(button); + + cell = row.insertCell(-1); + var button = document.createElement('input'); + button.setAttribute('type','button'); + button.setAttribute('name',email); + button.setAttribute('class','adminUserTableButton'); + button.setAttribute('onClick','adminUserRemoveUser('+index+')'); + cell.appendChild(button); + + index = index + 1; + }); + + $(".adminUserTableButton").button(); +} + +function adminUserModifyPopupSetup(index) { + localStorage.userTableIndex = index; +} + +function adminUserRemoveUser(index) { + var email = document.getElementById("userTableEmail:"+index).innerHTML; + + var r=confirm("User ["+email+"] is removed!!!"); + if (r==false) + { + return; + } + + var changeInfoList = []; + var changeInfoItem; + changeInfoItem = {"Type":"RemoveUser", "Email":email}; + changeInfoList.push(changeInfoItem); + + removeUser(changeInfoList, function () { + $.mobile.changePage("#adminUser"); + }); +} + diff --git a/dibs-web/public/javascripts/application.js b/dibs-web/public/javascripts/application.js new file mode 100644 index 0000000..9097d83 --- /dev/null +++ b/dibs-web/public/javascripts/application.js @@ -0,0 +1,15 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD +// GO AFTER THE REQUIRES BELOW. +// +//= require jquery +//= require jquery_ujs +//= require_tree . diff --git a/dibs-web/public/javascripts/build.js b/dibs-web/public/javascripts/build.js new file mode 100644 index 0000000..c2efd25 --- /dev/null +++ b/dibs-web/public/javascripts/build.js @@ -0,0 +1,344 @@ +/* + build.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function buildInit() { + if( $("#select-distribution").children().length == 0 ) { + queryDistribution( function(xml) { + $(xml).find("Data").find("DistributionName").each(function(){ + var name = $(this).text(); + + $("#select-distribution").append(""); + }); + + /* default distribution selection */ + $("#select-distribution option:eq(0)").attr("selected", "selected"); + $("#select-distribution").selectmenu('refresh'); + + // query Project list + buildQueryProjectList(); + + // query Running project list + //buildQueryRunningProjectList(); + + // add batch file selector event + //buildBatchFilePathSelector(); + }); + } else { + // query Project list + buildQueryProjectList(); + + // query Running project list + //buildQueryRunningProjectList(); + + // add batch file selector event + //buildBatchFilePathSelector(); + } +} + +function buildQueryProjectList() { + var distName = $("#select-distribution option:selected").val(); + + queryProjectsInDistribution( distName, function(xml) { + buildInitTable(); + var xmlBody = $(xml).find("Data"); + buildAddTableRow( xmlBody.find("BuildServerInfo").find("supportedOs"), + xmlBody.find("Project"), + xmlBody.find("OtherProject")); + buildAddBinaryTableRow( xmlBody.find("BinaryProject"), + xmlBody.find("OtherBinaryProject")); + }); +} + +function buildQueryRunningProjectList() { + var distName = $("#select-distribution option:selected").val(); + + queryRunningProjectsInfoInDistribution( distName, function(xml) { + var running_project = $(xml).find("RunProjectInfo"); + running_project.each(function(){ + var project_name = $(this).find("ProjectName").text(); + var project_os = $(this).find("ProjectOs").text(); + var project_type = $(this).find("ProjectType").text(); + var project_status = $(this).find("Status").text(); + + if (project_type == "GIT") { + var cell = document.getElementById("buildGitProjectTable"+":"+project_name+':'+project_os); + + if(cell){ + cell.setAttribute('bgcolor', '#fbff00'); + } + } + }); + }); +} + +function buildSelectAll(element) { + var checkboxes = document.getElementsByName(element.id); + var checked = element.checked; + for(var i in checkboxes) { + if(!checkboxes[i].disabled) { + checkboxes[i].checked = checked; + } + } +} + +function contains(a, obj) { + for (var i = 0; i < a.length; i++) { + if (a[i] == obj) { + return true; + } + } + return false; +} + +function buildInitTable() { + /* project table */ + var projectTable = document.getElementById("projectTable"); + + /* binary project table */ + var binaryProjectTable = document.getElementById("binaryProjectTable"); + + /* remove all table rows */ + while(projectTable.hasChildNodes()) + { + projectTable.removeChild(projectTable.firstChild); + } + while(binaryProjectTable.hasChildNodes()) + { + binaryProjectTable.removeChild(binaryProjectTable.firstChild); + } +} + +function buildAddTableRow(supportedOs, projectList, otherProjectList) { + // Table header + var idx = 0; + var tableHeader = ""; + var osArray = new Array(); + var projectTable = document.getElementById("projectTable"); + + // Project table header + tableHeader = "Project"; + supportedOs.each(function(){ + var osName = $(this).text(); + tableHeader = tableHeader + ""+osName+""; + + osArray[idx] = osName; + idx++; + }); + + tableHeader = tableHeader + "ALL"; + $("#projectTable").append(tableHeader); + + // table row - projectList + var index = 2; + + projectList.each(function(){ + var name = $(this).find("ProjectName").text(); + var osLists = $(this).find("OsList").text(); + var osList = osLists.split(","); + + var row = projectTable.insertRow(-1); + + var cell = row.insertCell(0); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('bgcolor', '#dcddc0'); + cell.innerHTML = name; + + for (i=0;i'; + row += '' + packageName + '' + row += 'REGISTER'; + row += '' + + $("#binaryProjectTable tr:last").after(row); + }); + + otherProjectList.each(function(){ + var name = $(this).find("ProjectName").text(); + var packageName = $(this).find("PackageName").text(); + var row = binaryProjectTable.insertRow(-1); + + /* add project name */ + var cell = row.insertCell(0); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('bgcolor', '#c0c0c0'); + cell.innerHTML = name; + + /* add package name */ + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('bgcolor', '#c0c0c0'); + cell.innerHTML = packageName; + + /* add empty cell for register */ + cell = row.insertCell(-1); + cell.setAttribute('style', 'text-align: left'); + cell.setAttribute('bgcolor', '#c0c0c0'); + cell.innerHTML = ""; + }); + + $('.binary_project_button').button(); + $('.binary_project_button').popupWindow({ + height:200, + width:400, + top:50, + left:50 + }); +} + +function buildBuildProject(type) { + var distName = $("#select-distribution option:selected").val(); + var buildProjectList = []; + + //var node_list = document.getElementsByTagName('input'); + var node_list = $("#build input") + for (var i = 0; i < node_list.length; i++) { + var node = node_list[i]; + + if (node.getAttribute('type') == "checkbox") { + if (node.checked == true) { + if (node.getAttribute('name') != "all-checkbox") { + var prjName = node.id.split(":")[1]; + var osName = node.id.split(":")[2]; + var buildData = { "distribution":distName, "buildType":type, "projectName" : prjName, "os" : osName }; + buildProjectList.push(buildData); + } + } + } + } + + buildProject(buildProjectList, function () { + $.mobile.changePage("#jobs"); + }); +} + +function buildUploadBinaryName(project_name) { + localStorage.distibutionName = $("#select-distribution option:selected").val(); + localStorage.uploadBinaryProjectName = project_name; +} + +function buildBatchFilePathSelector() { + var files, file, extension; + var filePath = document.getElementById("buildBatchFileUploadPath"); + var filePathOutputList = document.getElementById("buildBatchFileList"); + + filePath.addEventListener("change", function(e) { + files = e.target.files; + filePathOutputList.innerHTML = ""; + + for (var i = 0, len = files.length; i < len; i++) { + file = files[i]; + alert(file.webkitRelativePath); + filePathOutputList.innerHTML += "
  • " + file.name + "
  • "; + } + }, false); +} + +function buildClear() { + $("#select-distribution").empty(); + + buildInitTable(); +} diff --git a/dibs-web/public/javascripts/dibs-api.js b/dibs-web/public/javascripts/dibs-api.js new file mode 100644 index 0000000..9802a71 --- /dev/null +++ b/dibs-web/public/javascripts/dibs-api.js @@ -0,0 +1,392 @@ +/* + dibs-api.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +// controller: Users +function signUp(infoList, successFunction) { + var url = 'users/signup'; + postForServer(url, infoList, successFunction); +} + +function queryUserInfo(successFunction) { + var url = 'users/query'; + getInfoFromServer(url, successFunction); +} + +function modifyUserInfo(changeInfoList, successFunction) { + var url = 'users/modify'; + postForServer(url, changeInfoList, successFunction); +} + +// controller: Sessions +function login(infoList, successFunction) { + var url = 'sessions/login'; + postForServer(url, infoList, successFunction); +} + +function logout() { + var url = 'sessions/logout'; + deleteForServer(url, function() { + expireSession(); + dibsWebClear(); + }); +} + +// controller: projects +function queryDistribution(successFunction) { + var url = 'projects/queryDistribution'; + getInfoFromServer(url, successFunction); +} + +// controller : projects +function buildProject(changeInfoList, successFunction) { + var url = 'projects/buildProject'; + postForServer(url, changeInfoList, successFunction); +} + +function queryProjectsInDistribution(distName, successFunction) { + var url = 'projects/queryProjectsInDistribution/' + distName; + getInfoFromServer(url, successFunction); +} + +function queryRunningProjectsInfoInDistribution(distName, successFunction) { + var url = 'projects/queryRunningProjectsInfoInDistribution/' + distName; + getInfoFromServer(url, successFunction); +} + +function queryProjectsInfoInDistribution(distName, successFunction) { + var url = 'projects/queryProjectsInfoInDistribution/' + distName; + getInfoFromServer(url, successFunction); +} + +// controller : jobs +function queryJobsList(url, successFunction) { + return getInfoFromServer(url, successFunction); +} +function updateList(data, successFunction) { + var url = "jobs/update"; + var param = $.param(data); + return getInfoFromServerData(url, param, successFunction); +} +function queryJobsLog(job_id, next_line, successFunction) { + var url = "jobs/log/"+ job_id + "/" + next_line; + getInfoFromServerNoPreProcess(url, successFunction); +} +function cancelJobsJobid(job_id, successFunction) { + var url = "jobs/cancel/"+ job_id; + getInfoFromServerNoPreProcess(url, successFunction); +} + +// controller : admin_group +function queryAllGroup(successFunction) { + var url = 'admin_group/queryAllGroup'; + getInfoFromServer(url, successFunction); +} + +function queryGroupInfo(groupName, successFunction) { + var url = 'admin_group/queryGroupInfo/' + groupName; + getInfoFromServer(url, successFunction); +} + +function addGroup(changeInfoList, successFunction) { + var url = 'admin_group/addGroup'; + postForServer(url, changeInfoList, successFunction); +} + +function removeGroup(changeInfoList, successFunction) { + var url = 'admin_group/removeGroup'; + postForServer(url, changeInfoList, successFunction); +} + +function changeGroup(changeInfoList, successFunction) { + var url = 'admin_group/modifyGroup'; + postForServer(url, changeInfoList, successFunction); +} + +// controller : admin_user +function queryAllUser(successFunction) { + var url = 'admin_user/queryAllUser'; + getInfoFromServer(url, successFunction); +} + +function changeUser(changeInfoList, successFunction) { + var url = 'admin_user/modifyUser'; + postForServer(url, changeInfoList, successFunction); +} + +function removeUser(changeInfoList, successFunction) { + var url = 'admin_user/removeUser'; + postForServer(url, changeInfoList, successFunction); +} + +// controller : admin_server +function queryServerInfo(successFunction) { + var url = 'admin_server/queryServerInfo'; + getInfoFromServer(url, successFunction); +} + +function queryAllServer(successFunction) { + var url = 'admin_server/queryAllServer'; + getInfoFromServer(url, successFunction); +} + +function addRemoteBuildServer(changeInfoList, successFunction) { + var url = 'admin_server/addRemoteBuildServer'; + postForServer(url, changeInfoList, successFunction); +} + +function removeRemoteBuildServer(changeInfoList, successFunction) { + var url = 'admin_server/removeRemoteBuildServer'; + postForServer(url, changeInfoList, successFunction); +} + +function modifyRemoteBuildServer(changeInfoList, successFunction) { + var url = 'admin_server/modifyRemoteBuildServer'; + postForServer(url, changeInfoList, successFunction); +} + +function addOSCategory(changeInfoList, successFunction) { + var url = 'admin_server/addOsCategory'; + postForServer(url, changeInfoList, successFunction); +} + +function removeOSCategory(changeInfoList, successFunction) { + var url = 'admin_server/removeOsCategory'; + postForServer(url, changeInfoList, successFunction); +} + +function modifyOSCategory(changeInfoList, successFunction) { + var url = 'admin_server/modifyOsCategory'; + postForServer(url, changeInfoList, successFunction); +} + +function addSupportedOS(changeInfoList, successFunction) { + var url = 'admin_server/addSupportedOS'; + postForServer(url, changeInfoList, successFunction); +} + +function removeSupportedOS(changeInfoList, successFunction) { + var url = 'admin_server/removeSupportedOS'; + postForServer(url, changeInfoList, successFunction); +} + +function modifySupportedOS(changeInfoList, successFunction) { + var url = 'admin_server/modifySupportedOS'; + postForServer(url, changeInfoList, successFunction); +} + +function addServerInfo(changeInfoList, successFunction) { + var url = 'admin_server/addServerInfo'; + postForServer(url, changeInfoList, successFunction); +} + +function removeServerInfo(changeInfoList, successFunction) { + var url = 'admin_server/removeServerInfo'; + postForServer(url, changeInfoList, successFunction); +} + +function modifyServerInfo(changeInfoList, successFunction) { + var url = 'admin_server/modifyServerInfo'; + postForServer(url, changeInfoList, successFunction); +} + +// controller : admin_project +function queryAllProject(successFunction) { + var url = 'admin_project/queryAllProject'; + getInfoFromServer(url, successFunction); +} + +function queryProjectsInDistributionForAdmin(distName, successFunction) { + var url = 'admin_project/queryProjectsInDistributionForAdmin/' + distName; + getInfoFromServer(url, successFunction); +} + +function addProject(changeInfoList, successFunction) { + var url = 'admin_project/addProject'; + postForServer(url, changeInfoList, successFunction); +} + +function removeProject(changeInfoList, successFunction) { + var url = 'admin_project/removeProject'; + postForServer(url, changeInfoList, successFunction); +} + +function modifyProject(changeInfoList, successFunction) { + var url = 'admin_project/modifyProject'; + postForServer(url, changeInfoList, successFunction); +} + +// controller : admin_distribution +function queryAllDistribution(successFunction) { + var url = 'admin_distribution/queryAllDistribution'; + getInfoFromServer(url, successFunction); +} + +function queryDistributionInfo(distName, successFunction) { + var url = 'admin_distribution/queryDistributionInfo/' + distName; + getInfoFromServer(url, successFunction); +} + +function addDistribution(changeInfoList, successFunction) { + var url = 'admin_distribution/addDistribution'; + postForServer(url, changeInfoList, successFunction); +} + +function removeDistribution(changeInfoList, successFunction) { + var url = 'admin_distribution/removeDistribution'; + postForServer(url, changeInfoList, successFunction); +} + +function modifyDistribution(changeInfoList, successFunction) { + var url = 'admin_distribution/modifyDistribution'; + postForServer(url, changeInfoList, successFunction); +} + +function fullBuildDistribution(changeInfoList, successFunction) { + var url = 'admin_distribution/fullBuildDistribution'; + postForServer(url, changeInfoList, successFunction); +} + +// controller : admin +function queryAllOS(successFunction) { + var url = 'admin/queryAllOS'; + getInfoFromServer(url, successFunction); +} + +function queryAllOSCategory(successFunction) { + var url = 'admin/queryAllOSCategory'; + getInfoFromServer(url, successFunction); +} + +function getInfoFromServer(url, successFunction) { + return $.ajax({ + url: baseUrl+url, + type: 'GET', + dataType: 'xml', + timeout: 10000, + beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner + complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner + success: function(xml) { + setSessionInfo(xml); + successFunction(xml); + }, + error: function(jqXHR) { + errorProcess(jqXHR); + } + }); +} + +function getInfoFromServerNoPreProcess(url, successFunction) { + return $.ajax({ + url: baseUrl+url, + type: 'GET', + dataType: 'xml', + timeout: 10000, + success: function(xml) { + setSessionInfo(xml); + successFunction(xml); + }, + error: function(jqXHR) { + errorProcess(jqXHR); + } + }); +} + +function getInfoFromServerData(url, data, successFunction) { + return $.ajax({ + url: baseUrl+url, + type: 'GET', + dataType: 'xml', + text: 'JSONP', + data: data, + timeout: 10000, + success: function(xml) { + setSessionInfo(xml); + successFunction(xml); + }, + error: function(jqXHR) { + errorProcess(jqXHR); + } + }); +} + +function postForServer(url, changeInfoList, successFunction) { + $.ajax({ + url: baseUrl+url, + type: 'POST', + data: JSON.stringify({ ChangeInfoList: changeInfoList }), + dataType: 'json', + contentType: "application/json; charset=utf-8", + timeout: 10000, + beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner + complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner + success: function(xml) { + successFunction(xml); + }, + error: function(jqXHR) { + errorProcess(jqXHR); + } + }); +} + +function deleteForServer(url, successFunction) { + $.ajax({ + url: baseUrl+url, + type: 'DELETE', + async: false, + cache: false, + dataType: 'xml', + timeout: 1000, + beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner + complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner + success: function(xml) { + expireSession(); + dibsWebClear(); + }, + error: function(jqXHR) { + errorProcess(jqXHR); + } + }); +} + +function errorProcess(jqXHR){ + switch (parseInt(jqXHR.status)) { + case 401: + expireSession(); + break; + case 406: + alert("Internal server error : " + jqXHR.responseText); + break; + case 0: + console.error("Error response status : "+jqXHR.status); + break; + default: + console.error("Error response status : "+jqXHR.status); + alert("Server error : "+jqXHR.status); + break; + } +} diff --git a/dibs-web/public/javascripts/jobs.js b/dibs-web/public/javascripts/jobs.js new file mode 100644 index 0000000..cde6c98 --- /dev/null +++ b/dibs-web/public/javascripts/jobs.js @@ -0,0 +1,695 @@ +/* + jobs.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +var suggestion_list = new Array(); +var update_ajax; +var request_list = new Array(); +var request_idx = 0; + +$(function() { + $('#jobSearchSelect input[type="radio"]').checkboxradio().click(function() { + jobsSearchSelected(); + }); + + $('#jobStatusSelect input[type="radio"]').checkboxradio().click(function() { + jobsStatusSelected(); + }); + + $("#jobSearchInputText").on("input", function(e) { + var selectedValue = $('#jobSearchSelect').find("input[type='radio']:checked").val(); + switch(selectedValue) { + case "GROUP": + case "PROJECT": + suggestJobSearchList($(this).val()); + break; + default: + return; + } + }); + + $('#jobSearchInputText').keypress(function() { + if(event.keyCode == '13') { + searchJobInput(); + } + }); + + $('#jobSearchDate').keypress(function() { + if(event.keyCode == '13') { + searchJobDate(); + } + }); +}); + +function jobsInit() { + jobQueryDistribution(); +} + +function jobsSearchSelected() { + clearSuggestJobSearchList(); + + var selectedValue = $('#jobSearchSelect').find("input[type='radio']:checked").val(); + switch(selectedValue) { + case "ALL": + selectJobAll(); + break; + case "JOBID": + selectJobId(); + break; + case "USER": + selectUser(); + break; + case "GROUP": + selectGroup(); + break; + case "PROJECT": + selectProject(); + break; + case "DATE": + selectDate(); + break; + default: + alert("Sorry. Please, report bug."); + break; + } +} + +function jobsStatusSelected() { + var selectedValue = $('#jobStatusSelect').find("input[type='radio']:checked").val(); + switch(selectedValue) { + case "ALL": + jobsSearchSelected(); + break; + case "SUCCESS": + jobsSearchSelected(); + break; + case "WORKING": + jobsSearchSelected(); + break; + case "ERROR": + jobsSearchSelected(); + break; + default: + alert("Sorry. Please, report bug."); + break; + } +} + +function searchJobInput() { + var searchText = $("#jobSearchInputText").val() + if(searchText.length > 0) { + searchJob(searchText); + } +} + +function searchJobDate() { + var searchText = $("#jobSearchDate").val() + if(searchText.length > 0) { + searchJob(searchText); + } +} + +function searchJob(searchText) { + var distribution = $("#jobSelectDistribution option:selected").val(); + var selectedValue = $('#jobSearchSelect').find("input[type='radio']:checked").val(); + switch(selectedValue) { + case "ALL": + alert("Can't search on ALL!!"); + break; + case "JOBID": + queryJobListJobId(distribution, searchText); + break; + case "USER": + queryJobListUserName(distribution, searchText); + break; + case "GROUP": + queryJobListUserGroup(distribution, searchText); + break; + case "PROJECT": + queryJobListProject(distribution, searchText); + break; + case "DATE": + queryJobListDate(distribution, searchText); + break; + default: + alert("Sorry. Please, report bug."); + break; + } +} + +function selectJobAll() { + var distribution = $("#jobSelectDistribution option:selected").val(); + $("#jobDivSearchDate").hide(); + $("#jobDivSearchInput").hide(); + queryJobListAll(distribution); +} + +function selectJobId() { + $("#jobDivSearchDate").hide(); + $("#jobDivSearchInput").show(); + $("#jobSearchInputText").val("").textinput(); + clearJobList(); +} + +function selectUser() { + var distribution = $("#jobSelectDistribution option:selected").val(); + $("#jobDivSearchDate").hide(); + $("#jobDivSearchInput").show(); + + var name = sessionStorage.sessionInfoName; + $("#jobSearchInputText").val(name).textinput(); + + queryJobListUserName(distribution, name); +} + +function selectGroup() { + var distribution = $("#jobSelectDistribution option:selected").val(); + $("#jobDivSearchDate").hide(); + $("#jobDivSearchInput").show(); + + var group = sessionStorage.sessionInfoGroup; + $("#jobSearchInputText").val(group).textinput(); + + jobsQueryGroupList("JOBS"); + + queryJobListUserGroup(distribution, group); +} + +function selectProject() { + var distribution = $("#jobSelectDistribution option:selected").val(); + $("#jobDivSearchDate").hide(); + $("#jobDivSearchInput").show(); + clearJobList(); + + $("#jobSearchInputText").val("").textinput(); + + jobsQueryProjectsList(distribution); +} + +function selectDate() { + var distribution = $("#jobSelectDistribution option:selected").val(); + var today = new Date(); + var yyyy = today.getFullYear(); + var mm = today.getMonth()+1; //January is 0! + var dd = today.getDate(); //January is 0! + if(dd<10) { + dd='0'+dd; + } + if(mm<10) { + mm='0'+mm; + } + + var date = yyyy+'-'+mm+'-'+dd; + $('#jobSearchDate').val(date); + + $("#jobDivSearchInput").hide(); + $("#jobDivSearchDate").show(); + clearJobList(); + queryJobListDate(distribution, date); +} + +function clearJobList() { + $("#jobList").empty(); +} + +function queryJobListAll(distribution) { + queryJobListByButton("all", "", distribution, "LATEST"); +} + +function queryJobListJobId(distribution, jobId) { + queryJobListByButton("all", "", distribution, eval(parseInt(jobId) + 1)); +} +function queryJobListUserName(distribution, name) { + var encodingName = encodeURIComponent(name); + queryJobListByButton("user", encodingName, distribution, "LATEST"); +} + +function queryJobListUserGroup(distribution, group) { + queryJobListByButton("group", group, distribution, "LATEST"); +} + +function queryJobListProject(distribution, project) { + queryJobListByButton("project", project, distribution, "LATEST"); +} + +function queryJobListDate(distribution, date) { + queryJobListByButton("date", date, distribution, "LATEST"); +} + +function queryJobListByButton(condition, param, distribution, jobId) { + clearJobList(); + clearRequestList(); + var selectedStatus= $('#jobStatusSelect').find("input[type='radio']:checked").val(); + var request = queryJobList("jobs/list", condition, param, distribution, selectedStatus, jobId); + if(request != undefined) { + request.done(function() { + console.log("Start update"); + jobUpdateList(condition, param, distribution, selectedStatus); + }); + } +} + +function jobQueryDistribution() { + if( $("#jobSelectDistribution").children().length == 0 ) { + queryDistribution( function(xml) { + // remove old select options + $("#jobSelectDistribution").empty(); + $("#jobSelectDistribution").append(""); + + $(xml).find("Data").find("DistributionName").each(function(){ + var name = $(this).text(); + + $("#jobSelectDistribution").append(""); + }); + + /* default distribution selection */ + $("#jobSelectDistribution option:eq(0)").attr("selected", "selected"); + $("#jobSelectDistribution").selectmenu('refresh'); + + selectJobAll(); + }); + } else { + jobsSearchSelected(); + } +} + +function queryJobList(requestUrl, condition, param, queryDistribution, selectedStatus, jobId) { + var url = ""; + if(condition == "all") { + url = requestUrl+"/"+condition+"/"+queryDistribution+"/"+selectedStatus+"/"+jobId; + } + else { + url = requestUrl+"/"+condition+"/"+param+"/"+queryDistribution+"/"+selectedStatus+"/"+jobId; + } + console.log("url :"+url); + return queryJobsList(url, function(xml) { + var lastJobId = 0; + $(xml).find("JobList").find("Job").each(function(){ + var id = $(this).find("Id").text(); + var li = generateHtmlJobList($(this)); + + lastJobId = id; + $("#jobList").append(li).listview('refresh'); + + $("#jobs-li-link-"+id).popupWindow({ + height:900, + width:800, + top:30, + left:50 + }); + }); + + console.log("last job id :"+lastJobId); + if(lastJobId > 0) + { + var moreJobListUrl = 'queryJobList("'+requestUrl+'", "'+condition+'", "'+param+'", "'+queryDistribution+'", "'+selectedStatus+'", "'+lastJobId+'")'; + console.log(moreJobListUrl); + $('#moreJobList').attr("onClick", moreJobListUrl); + $('#moreJobList').removeClass('ui-disabled'); + } + else + { + $('#moreJobList').addClass('ui-disabled'); + } + $('#moreJobList').button('refresh'); + + }, errorProcess); +} + +function jobUpdateList(condition, param, distribution, selectedStatus) { + var latest_job_id= $("#jobList li").first().attr("title"); + if(latest_job_id == undefined) { + latest_job_id = 0; + } + var working_job_list = searchWorkingList(); + item = {"Condition":condition, "Param":param, "Distribution":distribution, "Status":selectedStatus, "LatestId":latest_job_id, "WorkingJobId":working_job_list}; + + var update_ajax = updateList(item, function(xml) { + var firstLi= $("#jobList li").first(); + + // Add new job list + $(xml).find("JobList").find("Job").each(function(){ + var id = $(this).find("Id").text(); + var li = generateHtmlJobList($(this)); + + $(li).insertBefore(firstLi); + $("#jobList").listview('refresh'); + $("#jobs-li-link-"+id).popupWindow({ + height:900, + width:800, + top:30, + left:50 + }); + console.log("ADD List :"+id); + }); + + // Update working job list + $(xml).find("WorkingJobList").find("Job").each(function(){ + var job_id = $(this).find("Id").text(); + var parent_job_id = $(this).find("ParentJobId").text(); + var job_status = $(this).find("Status").text(); + var start_time = $(this).find("StartTime").text(); + var end_time = $(this).find("EndTime").text(); + var font_color = "black"; + + switch(job_status) + { + case "ERROR" : + case "CANCELED" : + font_color = "red"; + break; + case "INITIALIZING" : + case "JUST_CREATED" : + case "PENDING" : + case "WORKING" : + case "REMOTE_WORKING" : + font_color = "blue"; + break; + case "WAITING" : + font_color = "green"; + break; + case "FINISHED" : + font_color = "black"; + break; + default: + console.error(job_status+" status is not define."); + font_color = "black"; + break; + } + + // in case, exist job list element or not exist + if($("#jobs-li-"+job_id).length != 0) { + var html_status = ''+job_status+''; + var html_time = 'TIME: ' +start_time+ ' ~ '+end_time+ ''; + $("#jobs-li-status-"+job_id).html(html_status); + $("#jobs-li-time-"+job_id).html(html_time); + console.log("UPDATE List :"+job_id); + } + else { + var next_parent_job_li = $("#jobs-li-"+parent_job_id).nextAll(".jobs-li-header").first(); + console.log(parent_job_id); + console.log($("#jobs-li-"+parent_job_id)); + console.log(next_parent_job_li); + console.log(next_parent_job_li.text()); + + var li = generateHtmlJobList($(this)); + + $(li).insertBefore(next_parent_job_li); + $("#jobList").listview('refresh'); + $("#jobs-li-link-"+job_id).popupWindow({ + height:900, + width:800, + top:30, + left:50 + }); + console.log("ADD child list :"+job_id); + } + }); + }); + + var idx = addRequestList(update_ajax); + update_ajax.done(function() { + console.log("update complete. retry in 2 sec."); + setTimeout(function(){ + if(isPolling(idx) && $.mobile.activePage.attr('id') == "jobs" && idx < 900) { + console.log("Update request."); + request_list[idx].polling = false; + jobUpdateList(condition, param, distribution, selectedStatus); + } + else { + console.log("Stop update."); + } + }, 2000); + }); +} + +function clearSuggestJobSearchList() { + $("#jobSearchList").empty(); +} + +function jobsQueryGroupList() { + suggestion_list = []; + + queryAllGroup( function(xml) { + var idx = 0; + + $(xml).find("Data").find("GroupName").each(function(){ + suggestion_list[idx]= $(this).text(); + idx++; + }); + }, errorProcess); +} + +function suggestJobSearchList(inputText) { + var sugList = $("#jobSearchList"); + + if(inputText.length < 1) { + sugList.html(""); + sugList.listview("refresh"); + } else { + var str = ""; + var suggestion = ""; + for(var i=0, len=suggestion_list.length; i= 0) + { + str += "
  • "+suggestion+"
  • "; + } + } + sugList.html(str); + sugList.listview("refresh"); + } +} + +function jobSuggestListClick(suggestText) { + $("#jobSearchInputText").val(suggestText); + $("#jobSearchList").empty(); + + var startIndex = suggestText.search(/\[/); + var endIndex = suggestText.search('\]'); + + if(startIndex > 0 && endIndex >0) { + project = suggestText.substr(0, startIndex); + distribution = suggestText.substr(startIndex+1, endIndex-startIndex-1); + queryJobListProject(distribution, project); + } + else { + searchJob(suggestText); + } +} + +function jobsQueryProjectsList() { + var distribution = $("#jobSelectDistribution option:selected").val(); + suggestion_list = []; + + if(distribution == "ALL") { + queryAllProject(function(xml) { + var idx = 0; + + $(xml).find("Data").find("Project").each(function(){ + var projectName = $(this).find("Name").text(); + var distName = $(this).find("DistName").text(); + suggestion_list[idx]= projectName+"["+distName+"]" + idx++; + }); + }); + } + else { + queryProjectList(distribution, function(xml) { + var idx = 0; + + $(xml).find("Data").find("Project").each(function(){ + suggestion_list[idx]= $(this).find("ProjectName").text(); + idx++; + }); + }); + } +} + +function jobsClear() { + $("#jobSelectDistribution").empty(); + clearJobList(); +} + +function generateHtmlJobList(xml) { + var id = xml.find("Id").text(); + var distribution = xml.find("Distribution").text(); + var projectName = xml.find("ProjectName").text(); + var jobType = xml.find("JobType").text(); + var jobAttribute = xml.find("JobAttribute").text(); + var os = xml.find("Os").text(); + var jobStatus = xml.find("Status").text(); + var userName = xml.find("UserName").text(); + var startTime = xml.find("StartTime").text(); + var endTime = xml.find("EndTime").text(); + var li = ""; + var font_color = "black"; + + switch(jobStatus) + { + case "ERROR" : + case "CANCELED" : + font_color = "red"; + break; + case "INITIALIZING" : + case "JUST_CREATED" : + case "PENDING" : + case "WORKING" : + case "REMOTE_WORKING" : + font_color = "blue"; + break; + case "WAITING" : + font_color = "green"; + break; + case "FINISHED" : + font_color = "black"; + break; + default: + console.error(job_status+" status is not define."); + font_color = "black"; + break; + } + + if(jobAttribute == "SINGLE") + { + li = '
  • ' + + ''+id+ ' ' +projectName+ ''+distribution+'
  • ' + + '
  • ' + + '' + + '

    ' +projectName+ '

    ' + + '

    ID : ' +id+ '

    ' + + '

    TYPE : ' +jobType+ '

    ' + + '

    OS : ' + os + '

    ' + + '

    USER : ' +userName+ '

    ' + + '

    TIME: ' +startTime+ ' ~ '+endTime+ '

    '; + + li = li + '

    '+jobStatus+'

    '; + li = li + ''; + li = li + '
  • '; + } + else if(jobAttribute == "MULTI") + { + li = '
  • ' + + ''+id+ ' ' +jobAttribute+ ''+distribution+'
  • ' + + '
  • ' + + '' + + '

    USER : ' +userName+ '

    ' + + '

    TIME: ' +startTime+ ' ~ '+endTime+ '

    '; + + ''; + + li = li + '

    '+jobStatus+'

    '; + li = li + ''; + li = li + '
  • '; + } + else if(jobAttribute == "CHILD") + { + li = '
  • ' + + '' + + '

    ' +projectName+ '

    ' + + '

    ID : ' +id+ '

    ' + + '

    TYPE : ' +jobType+ '

    ' + + '

    OS : ' +os+ '

    ' + + '

    TIME: ' +startTime+ ' ~ '+endTime+ '

    '; + + ''; + + li = li + '

    '+jobStatus+'

    '; + li = li + ''; + li = li + '
  • '; + } + + return li; +} + +function searchWorkingList() { + working_job_array = new Array(); + $("#jobList .jobs-list-data").each(function(index) { + var job_attr = $(this).find(".jobs-li-hidden-attr").text(); + var job_id = $(this).find(".jobs-li-hidden-id").text(); + var job_status= $(this).find(".jobs-li-status").text(); + switch(job_status) + { + case "INITIALIZING" : + case "JUST_CREATED" : + case "PENDING" : + case "WORKING" : + case "REMOTE_WORKING" : + case "WAITING" : + if(job_attr != "CHILD") { + working_job_array.push(job_id); + } + break; + default: + break; + } + }); + return working_job_array; +} + +/* For background update AJAX */ +function classAjax() { + var polling = false; + var ajaxObj = undefined; +} + +function addRequestList(ajaxObj) { + var class_ajax = new classAjax(); + class_ajax.polling = true; + class_ajax.ajaxObj = ajaxObj; + + return request_list.push(class_ajax) - 1; +} + +function clearRequestList() { + while(request_list.length > 0) { + var last_request = request_list[request_list.length - 1]; + if(last_request.polling == true && last_request.ajaxObj != undefined) { + last_request.ajaxObj.abort(); + } + request_list.pop(); + } + console.log("Clear all update."); +} + +function isPolling(idx) { + if(request_list[idx] != undefined) { + return request_list[idx].polling; + } + else { + return false; + } +} + diff --git a/dibs-web/public/javascripts/log.js b/dibs-web/public/javascripts/log.js new file mode 100644 index 0000000..607b68c --- /dev/null +++ b/dibs-web/public/javascripts/log.js @@ -0,0 +1,184 @@ +/* + log.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +var request; +var stop = 1; + +var baseUrl; +var job_id; +var last_line = 0; + +var init = function () { + console.log("init() called"); + var myUrl = location.href; + var varCut = myUrl.indexOf("?"); + var varCheck = myUrl.substring(varCut+1); + eval(varCheck); + + job_id = jobid; + $('#job-info-id').text(job_id); + console.log(job_id); + + var baseCut = myUrl.indexOf("log.html"); + + baseUrl = myUrl.substring(0, baseCut); + console.log("base url:"+baseUrl); + + queryLog(); +}; + +$(document).ready(init); + +function queryLog() +{ + var next_line = Number(last_line) + 1; + queryJobsLog(job_id, next_line, function(xml) { + /* pre-process for header */ + job_id = $(xml).find("Data").find("JobId").text(); + var distribution = $(xml).find("Data").find("Distribution").text(); + var project = $(xml).find("Data").find("Project").text(); + var builder = $(xml).find("Data").find("Builder").text(); + var job_status = $(xml).find("Data").find("Status").text(); + var time = $(xml).find("Data").find("Time").text(); + var conti = Number($(xml).find("Data").find("Continue").text()); + var working_status = 0; + + $('#job-info-distribution').html(distribution); + $('#job-info-project').html(project); + $('#job-info-builder').html(builder); + $('#job-info-status').html(job_status); + switch(job_status) + { + case "ERROR" : + case "CANCELED" : + $('#job-info-status').css("color","red"); + $('#job-info-cancel input').attr("disabled", true); + working_status = 0; + break; + case "INITIALIZING" : + case "JUST_CREATED" : + case "PENDING" : + case "WORKING" : + case "REMOTE_WORKING" : + $('#job-info-status').css("color","blue"); + working_status = 1; + break; + case "WAITING" : + $('#job-info-status').css("color","green"); + working_status = 1; + break; + case "FINISHED" : + $('#job-info-status').css("color","black"); + $('#job-info-cancel input').attr("disabled", true); + working_status = 0; + break; + default: + console.error(job_status+" status is not define."); + $('#job-info-cancel input').attr("disabled", true); + working_status = 0; + break; + } + + /* Insert data */ + $(xml).find("Data").find("LogData").each(function() { + var insertTable = document.getElementById("logTable"); + var insertRow = document.createElement("tr"); + var insertCel1 = document.createElement("td"); + var insertCel2 = document.createElement("td"); + + var line_number = $(this).attr("Line"); + var line_data = $(this).text(); + + insertCel1.width = '30'; + insertCel1.style.textAlign = 'right'; + insertCel1.style.cellpacing = '5'; + insertCel1.innerHTML = line_number; + last_line = line_number; + + insertCel2.style.textAlign = 'left'; + insertCel2.innerHTML = line_data; + + insertRow.appendChild(insertCel1); + insertRow.appendChild(insertCel2); + + insertTable.appendChild(insertRow); + + }); + + if(working_status == 1){ + console.log("scroll"); + scrollToBottom(); + } + + autoQueryLog(conti, working_status); + }); +} + +function autoQueryLog(conti, working_status) { + if(conti && stop) { + queryLog(); + } + + if(working_status == 1 && stop) { + console.log("status is working. try request"); + setTimeout(function(){queryLog()}, 3000); + } +} + +function stopLog() { + stop = 0; +} + +function moreLog() { + stop = 1; + queryLog(); +} + +function cancelJob() { + cancelJobsJobid(job_id, function(xml) { + alert("Reqeusted cancel job : "+job_id); + }); +} + +function getYScroll() +{ + var yScroll; + if (window.innerHeight && window.scrollMaxY) { + yScroll = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac + yScroll = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + yScroll = document.body.offsetHeight; + } + return yScroll; +} + +function scrollToBottom() { + window.scrollTo(0,getYScroll()); +} + diff --git a/dibs-web/public/javascripts/main.js b/dibs-web/public/javascripts/main.js new file mode 100644 index 0000000..bb60f7f --- /dev/null +++ b/dibs-web/public/javascripts/main.js @@ -0,0 +1,337 @@ +/* + main.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +//Initialize function +var baseUrl = ""; + +var init = function () { + console.log("init() called"); + var myUrl = location.href; + var urlCut = myUrl.indexOf("index.html"); + var sharpCut = myUrl.indexOf("#"); + + if(urlCut > 0) { + baseUrl = myUrl.substring(0, urlCut); + } + else if(sharpCut > 0) { + baseUrl = myUrl.substring(0, sharpCut); + } + else { + baseUrl = window.location.href; + } + console.log("base url:"+baseUrl); +}; +$(document).ready(init); + +$.ajaxSetup({ + beforeSend: function(xhr) { + xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')); + } +}); + + +$( document ).bind( "pageshow", function( event, data ){ +}); + +$( document ).bind( "pagechange", function( event, data ){ + var id = $.mobile.activePage.attr('id'); + + switch(id){ + case "index": + generateNavigationBar(id); + break; + case "signup": + clearFormData('signupForm'); + break; + case "login": + clearFormData('loginForm'); + break; + case "projects": + generateNavigationBar(id); + projectsInit(id); + break; + case "build": + generateNavigationBar(id); + buildInit(id); + break; + case "jobs": + generateNavigationBar(id); + jobsInit(); + break; + case "log": + logInit(); + break; + case "adminUser": + generateNavigationBar(id); + adminUserInit(); + break; + case "adminGroup": + generateNavigationBar(id); + adminGroupInit(); + break; + case "adminServer": + generateNavigationBar(id); + adminServerInit(); + break; + case "adminProject": + generateNavigationBar(id); + adminProjectInit(); + break; + case "adminDistribution": + generateNavigationBar(id); + adminDistributionInit(); + break; + case "modifyDistribution": + adminDistributionModifyPopupInit(); + break; + case "adminUserModifyPopup": + adminUserModifyPopupInit(); + break; + case "modifyBinaryProject": + adminProjectModifyBinaryProjectInit(); + break; + case "modifyGitProject": + adminProjectModifyGitProjectInit(); + break; + case "adminGroupAddPopup": + adminGroupAddInit(); + break; + case "adminGroupModifyPopup": + adminGroupModifyInit(); + break; + case "adminServerModifyRemoteBuildServer": + adminServerModifyRemoteBuildServerInit(); + break; + case "addGitProject": + adminProjectAddGitInit(); + break; + case "addBinaryProject": + adminProjectAddBinaryInit(); + break; + case "adminServerAddSupportedOs": + adminServerAddSupportedOsInit(); + break; + case "adminServerRemoveOSCategory": + adminServerRemoveOSCategoryInit(); + break; + case "signup": + //queryGroupListForSignup(); + break; + default: + break; + } + + // Call check session info + checkSessionInfo(); +}); + +$( document ).bind( "mobileinit", function() { + $.support.cors = true; + $.support.cors = true; + $.mobile.pushStateEnabled = false; +}); + +function clearFormData(elementId){ + $("#"+elementId).find(':input').each(function() { + switch(this.type) { + case 'text': + case 'password': + case 'select-multiple': + case 'select-one': + case 'textarea': + $(this).val(''); + break; + case 'checkbox': + case 'radio': + $(this).checked = false; + break; + } + }); +} + +function generateNavigationBar(id) { + if(sessionStorage.sessionInfoEmail) + { + var admin = sessionStorage.sessionInfoAdmin; + if(admin == "TRUE") + { + generateNavigationBarAdmin(id); + } + else + { + generateNavigationBarUser(id); + } + } else { + $("#"+id+"-navigationBar").empty(); + } +} + +function generateNavigationBarUser(id) { + var naviHtml = "" + naviHtml = '
  • BUILD
  • '; + switch(id){ + case "projects": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + break; + case "build": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + break; + case "jobs": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + break; + default: + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + break; + } + + $("#"+id+"-navigationBar").empty(); + $("#"+id+"-navigationBar").append(naviHtml).listview("refresh"); +} + +function generateNavigationBarAdmin(id) { + var naviHtml = "" + naviHtml = '
  • BUILD
  • '; + switch(id){ + case "projects": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "build": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "jobs": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "adminUser": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "adminGroup": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "adminServer": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "adminDistribution": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + case "adminProject": + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + default: + naviHtml += '
  • Projects
  • '; + naviHtml += '
  • Build
  • '; + naviHtml += '
  • Jobs
  • '; + naviHtml += '
  • ADMIN
  • '; + naviHtml += '
  • User
  • '; + naviHtml += '
  • Group
  • '; + naviHtml += '
  • Server
  • '; + naviHtml += '
  • Distribution
  • '; + naviHtml += '
  • Project
  • '; + break; + } + + $("#"+id+"-navigationBar").empty(); + $("#"+id+"-navigationBar").append(naviHtml).listview("refresh"); +} + +function dibsWebClear(){ + projectsClear(); + buildClear(); + jobsClear(); +} diff --git a/dibs-web/public/javascripts/popup-window.js b/dibs-web/public/javascripts/popup-window.js new file mode 100644 index 0000000..fd5d493 --- /dev/null +++ b/dibs-web/public/javascripts/popup-window.js @@ -0,0 +1,90 @@ +/* + popup-window.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +(function($){ + $.fn.popupWindow = function(instanceSettings){ + + return this.each(function(){ + + $(this).click(function(){ + + $.fn.popupWindow.defaultSettings = { + centerBrowser:0, // center window over browser window? {1 (YES) or 0 (NO)}. overrides top and left + centerScreen:0, // center window over entire screen? {1 (YES) or 0 (NO)}. overrides top and left + height:500, // sets the height in pixels of the window. + left:0, // left position when the window appears. + location:1, // determines whether the address bar is displayed {1 (YES) or 0 (NO)}. + menubar:0, // determines whether the menu bar is displayed {1 (YES) or 0 (NO)}. + resizable:0, // whether the window can be resized {1 (YES) or 0 (NO)}. Can also be overloaded using resizable. + scrollbars:1, // determines whether scrollbars appear on the window {1 (YES) or 0 (NO)}. + status:0, // whether a status line appears at the bottom of the window {1 (YES) or 0 (NO)}. + width:500, // sets the width in pixels of the window. + windowName:null, // name of window set from the name attribute of the element that invokes the click + windowURL:null, // url used for the popup + top:0, // top position when the window appears. + toolbar:0 // determines whether a toolbar (includes the forward and back buttons) is displayed {1 (YES) or 0 (NO)}. + }; + + settings = $.extend({}, $.fn.popupWindow.defaultSettings, instanceSettings || {}); + + var windowFeatures = 'height=' + settings.height + + ',width=' + settings.width + + ',toolbar=' + settings.toolbar + + ',scrollbars=' + settings.scrollbars + + ',status=' + settings.status + + ',resizable=' + settings.resizable + + ',location=' + settings.location + + ',menuBar=' + settings.menubar; + + settings.windowName = this.name || settings.windowName; + settings.windowURL = this.href || settings.windowURL; + var centeredY,centeredX; + + if(settings.centerBrowser){ + + if ($.browser.msie) {//hacked together for IE browsers + centeredY = (window.screenTop - 120) + ((((document.documentElement.clientHeight + 120)/2) - (settings.height/2))); + centeredX = window.screenLeft + ((((document.body.offsetWidth + 20)/2) - (settings.width/2))); + }else{ + centeredY = window.screenY + (((window.outerHeight/2) - (settings.height/2))); + centeredX = window.screenX + (((window.outerWidth/2) - (settings.width/2))); + } + window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + centeredX +',top=' + centeredY).focus(); + }else if(settings.centerScreen){ + centeredY = (screen.height - settings.height)/2; + centeredX = (screen.width - settings.width)/2; + window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + centeredX +',top=' + centeredY).focus(); + }else{ + window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + settings.left +',top=' + settings.top).focus(); + } + return false; + }); + + }); + }; +})(jQuery); diff --git a/dibs-web/public/javascripts/post-process.js b/dibs-web/public/javascripts/post-process.js new file mode 100644 index 0000000..0c0aaaa --- /dev/null +++ b/dibs-web/public/javascripts/post-process.js @@ -0,0 +1,35 @@ +/* + post-process.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +$('.uploadWindow').popupWindow({ + height:200, + width:400, + top:50, + left:50 +}); + diff --git a/dibs-web/public/javascripts/projects.js b/dibs-web/public/javascripts/projects.js new file mode 100644 index 0000000..2288665 --- /dev/null +++ b/dibs-web/public/javascripts/projects.js @@ -0,0 +1,178 @@ +/* + projects.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +function projectsInit() { + if( $("#projects-select-distribution").children().length == 0 ) { + queryDistribution( function(xml) { + // remove old select options + $("#projects-select-distribution").empty(); + + $(xml).find("Data").find("DistributionName").each(function(){ + var name = $(this).text(); + + $("#projects-select-distribution").append(""); + }); + + /* default distribution selection */ + $("#projects-select-distribution option:eq(0)").attr("selected", "selected"); + $("#projects-select-distribution").selectmenu('refresh'); + + projectsQueryProjectListType("MY"); + $('#projectsSearchSelect input[type="radio"]').attr("checked",false).checkboxradio("refresh"); + $('#projectsSearchSelect input[type="radio"]:first').attr("checked",true).checkboxradio("refresh"); + }); + } else { + projectsQueryProjectListType("MY"); + $('#projectsSearchSelect input[type="radio"]').attr("checked",false).checkboxradio("refresh"); + $('#projectsSearchSelect input[type="radio"]:first').attr("checked",true).checkboxradio("refresh"); + } +} + +function projectsQueryProjectListType(queryType) { + var distName = $("#projects-select-distribution option:selected").val(); + + queryProjectsInfoInDistribution( distName, function(xml) { + var projectList = document.getElementById("projects-project-list"); + + /* remove all list */ + while(projectList.hasChildNodes()) + { + projectList.removeChild(projectList.firstChild); + } + + $(xml).find("Data").find("ProjectList").find("Project").each(function(){ + switch(queryType) { + case "ALL": + projectsAppendProjectList($(this), projectList); + break; + case "MY": + var groupAccess = $(this).find("GroupAccess").text(); + if(groupAccess == "TRUE") { + projectsAppendProjectList($(this), projectList); + } + break; + case "GIT": + var type = $(this).find("Type").text(); + if(type == "GIT") { + projectsAppendProjectList($(this), projectList); + } + break; + case "BINARY": + var type = $(this).find("Type").text(); + if(type == "BINARY") { + projectsAppendProjectList($(this), projectList); + } + break; + default: + ; + } + }); + + $('.projects-project-list-collapsible').collapsible(); + $('.projects-project-list-listview').listview(); + + }); +} + +function projectsAppendProjectList( project, projectList ) { + var name = project.find("Name").text(); + var type = project.find("Type").text(); + var groupAccess = project.find("GroupAccess").text(); + var maintainer = project.find("Maintainer").text(); + + var div = document.createElement('div'); + div.setAttribute('data-role', 'collapsible'); + div.setAttribute('data-inset', 'false'); + div.setAttribute('data-mini', 'true'); + div.setAttribute('class', 'projects-project-list-collapsible'); + if(groupAccess == "TRUE") { + div.setAttribute('data-theme', "b"); + } + else { + div.setAttribute('data-theme', "d"); + } + projectList.appendChild(div); + + var h2 = document.createElement('h2'); + h2.innerHTML = ''+name+''+type+''; + div.appendChild(h2); + + var infoLine = document.createElement('p'); + infoLine.setAttribute('style', 'font-size: 12px'); + infoLine.innerHTML = "Maintainer : "+maintainer+"

    "; + div.appendChild(infoLine); + + var ul = document.createElement('ul'); + ul.setAttribute('data-role', "listview"); + ul.setAttribute('class', "projects-project-list-listview"); + ul.setAttribute('data-filter-theme', "c"); + ul.setAttribute('data-divider-theme', "c"); + div.appendChild(ul); + + project.find("ProjectOs").each(function(){ + var osName = $(this).find("OsName").text(); + + var li = document.createElement('li'); + li.setAttribute('style', 'font-size: 12px'); + li.setAttribute('data-role', "list-divider") + li.innerHTML = ""+osName+""; + ul.appendChild(li); + + $(this).find("Package").each(function(){ + var packageName = $(this).find("PackageName").text(); + var packageVersion = $(this).find("PackageVersion").text(); + var startTime = $(this).find("StartTime").text(); + var endTime= $(this).find("EndTime").text(); + var userName = $(this).find("UserName").text(); + var userEmail = $(this).find("UserEmail").text(); + + if(packageName != "") + { + var liInfo = document.createElement('li'); + liInfo.setAttribute('style', 'font-size: 12px'); + var info = "

    "+packageName+" "+packageVersion+"

    "; + info += "

    Lastest build time : "+startTime+" ~ "+endTime+"

    "; + info += "

    Lastest build user : "+userName+" ["+userEmail+"]

    "; + liInfo.innerHTML = info; + ul.appendChild(liInfo); + } + }); + }); +} + +function projectsClear() { + $("#projects-select-distribution").empty(); + + var projectList = document.getElementById("projects-project-list"); + /* remove all list */ + while(projectList.hasChildNodes()) + { + projectList.removeChild(projectList.firstChild); + } +} + diff --git a/dibs-web/public/javascripts/session.js b/dibs-web/public/javascripts/session.js new file mode 100644 index 0000000..12582dc --- /dev/null +++ b/dibs-web/public/javascripts/session.js @@ -0,0 +1,146 @@ +/* + session.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +$(function() { + $('#login-password').keypress(function() { + if(event.keyCode == '13') { + sessionLogin(); + } + }); +}); + +function setSessionInfo(xml){ + var email = $(xml).find("Header").find("UserInfo").find("Email").text(); + var name = $(xml).find("Header").find("UserInfo").find("Name").text(); + var admin = $(xml).find("Header").find("UserInfo").find("Admin").text(); + var group; + var idx = 0; + $(xml).find("Header").find("UserInfo").find("GroupList").find("Group").each(function() { + if(idx == 0) { + group = $(this).find("GroupName").text(); + } + }); + + sessionStorage.sessionInfoEmail = email; + sessionStorage.sessionInfoName = name; + sessionStorage.sessionInfoGroup = group; + sessionStorage.sessionInfoAdmin = admin; + + checkSessionInfo(); +} + +function checkSessionInfo(){ + var email = sessionStorage.sessionInfoEmail; + var name = sessionStorage.sessionInfoName; + + if(email) + { + sessionHtml = '
    '; + sessionHtml += '

    '+name+' | '; + sessionHtml += 'Log out

    '; + } + else + { + sessionHtml = '
    '; + sessionHtml += 'Sign up'; + sessionHtml += 'Log in
    '; + } + $(".sessionInfo").html(sessionHtml).trigger("create"); +} + +function clearSessionInfo(){ + sessionStorage.sessionInfoEmail = ""; + sessionStorage.sessionInfoName = ""; + sessionStorage.sessionInfoGroup = ""; + sessionStorage.sessionInfoAdmin = ""; +} + +function expireSession(){ + clearSessionInfo(); + $.mobile.changePage("index.html"); + generateNavigationBar("index"); +} + +function sessionLogin() { + var infoList = []; + var infoItem; + var email = $('#login-email').val(); + var password = $('#login-password').val(); + + if(email == ""){ + alert("Email is invalid"); + return false; + } + + if(password == ""){ + alert("Password is invalid"); + return false; + } + + changeInfoItem = {"Type":"ModifyUser", "Email":email, "Password":password }; + infoList.push(changeInfoItem); + + login(infoList, function (json) { + var result = json.Result; + var message = json.UserInfo.Message; + var email = json.UserInfo.Eamil; + var name = json.UserInfo.Name; + var group = json.UserInfo.GroupName; + var admin = json.UserInfo.Admin; + + if(result == "SUCCESS") + { + sessionStorage.sessionInfoEmail = email; + sessionStorage.sessionInfoName = name; + sessionStorage.sessionInfoGroup = group; + sessionStorage.sessionInfoAdmin = admin; + $.mobile.changePage("#index"); + } + else + { + alert(message); + } + }); +} + +function signupQueryGroupList() { + queryAllGroup( function(xml) { + $("#applyGroupRadio").children().remove(); + + var newHtml ='
    Apply for group :'; + $(xml).find("Data").find("GroupName").each(function(){ + var name = $(this).text(); + newHtml += ''; + newHtml += ''; + }); + console.log(newHtml); + $("#applyGroupRadio").append(newHtml).trigger('create'); + $("#applyGroupRadio div[role='heading']").attr("style","text-align: left; font-size: 12px"); + }, errorProcess); +} + diff --git a/dibs-web/public/javascripts/user.js b/dibs-web/public/javascripts/user.js new file mode 100644 index 0000000..70d8689 --- /dev/null +++ b/dibs-web/public/javascripts/user.js @@ -0,0 +1,136 @@ +/* + user.js + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Sungmin Kim +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +*/ + +$(function() { + $('#user-password-confirmation').keypress(function() { + if(event.keyCode == '13') { + userSignUp(); + } + }); +}); + +function userSignUp() { + var infoList = []; + var infoItem; + var email = $('#user-email').val(); + var name = $('#user-name').val(); + var password = $('#user-password').val(); + var password_confirm = $('#user-password-confirmation').val(); + var emailCheckReg = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/ + + if(email == "" || !emailCheckReg.test(email)){ + alert("Email is invalid"); + return false; + } + if(name == ""){ + alert("Name is invalid"); + return false; + } + + if(password == ""){ + alert("Password is invalid"); + return false; + } + + if(password != password_confirm){ + alert("Password is different"); + return false; + } + + changeInfoItem = {"Type":"ModifyUser", "Email":email, "Name":name, "Password":password, "PasswordConfirm":password_confirm}; + infoList.push(changeInfoItem); + + signUp(infoList, function (json) { + alert("Success sign up"); + + var result = json.Result; + var message = json.UserInfo.Message; + var email = json.UserInfo.Eamil; + var name = json.UserInfo.Name; + var group = json.UserInfo.GroupName; + var admin = json.UserInfo.Admin; + + if(result == "SUCCESS") + { + sessionStorage.sessionInfoEmail = email; + sessionStorage.sessionInfoName = name; + sessionStorage.sessionInfoGroup = group; + sessionStorage.sessionInfoAdmin = admin; + $.mobile.changePage("#index"); + } + else + { + alert(message); + } + }); +} + +function userQueryUserInfo() { + queryUserInfo( function (xml) { + var email = $(xml).find("Data").find("User").find("Email").text(); + var name = $(xml).find("Data").find("User").find("Name").text(); + + $("#popup-user-info-email").val(email).textinput(); + $("#popup-user-info-name").val(name).textinput(); + }); +} + +function userModifyUserInfo() { + var changeInfoList = []; + var changeInfoItem; + var email = $('#popup-user-info-email').val(); + var name = $('#popup-user-info-name').val(); + var password = $('#popup-user-info-password').val(); + var password_confirm = $('#popup-user-info-password-confirm').val(); + + if(email == ""){ + alert("Email is invalid"); + return false; + } + if(name == ""){ + alert("Name is invalid"); + return false; + } + + if(password == ""){ + alert("Password is invalid"); + return false; + } + + if(password != password_confirm){ + alert("Password is different"); + return false; + } + + changeInfoItem = {"Type":"ModifyUser", "Email":email, "Name":name, "Password":password, "PasswordConfirm":password_confirm}; + changeInfoList.push(changeInfoItem); + + modifyUserInfo(changeInfoList, function (xml) { + alert("Success changed information"); + }); +} diff --git a/dibs-web/public/log.html b/dibs-web/public/log.html new file mode 100644 index 0000000..ec4c4c4 --- /dev/null +++ b/dibs-web/public/log.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + +
    + +
    + + + + diff --git a/dibs-web/public/robots.txt b/dibs-web/public/robots.txt new file mode 100644 index 0000000..085187f --- /dev/null +++ b/dibs-web/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / diff --git a/dibs-web/public/stylesheets/application.css b/dibs-web/public/stylesheets/application.css new file mode 100644 index 0000000..3192ec8 --- /dev/null +++ b/dibs-web/public/stylesheets/application.css @@ -0,0 +1,13 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require_self + *= require_tree . + */ diff --git a/dibs-web/public/stylesheets/images/ajax-loader.gif b/dibs-web/public/stylesheets/images/ajax-loader.gif new file mode 100644 index 0000000..fd1a189 Binary files /dev/null and b/dibs-web/public/stylesheets/images/ajax-loader.gif differ diff --git a/dibs-web/public/stylesheets/images/ajax-loader.png b/dibs-web/public/stylesheets/images/ajax-loader.png new file mode 100644 index 0000000..13b208d Binary files /dev/null and b/dibs-web/public/stylesheets/images/ajax-loader.png differ diff --git a/dibs-web/public/stylesheets/images/icons-18-black.png b/dibs-web/public/stylesheets/images/icons-18-black.png new file mode 100644 index 0000000..ce1b758 Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-18-black.png differ diff --git a/dibs-web/public/stylesheets/images/icons-18-white.png b/dibs-web/public/stylesheets/images/icons-18-white.png new file mode 100644 index 0000000..1ab0127 Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-18-white.png differ diff --git a/dibs-web/public/stylesheets/images/icons-36-black.png b/dibs-web/public/stylesheets/images/icons-36-black.png new file mode 100644 index 0000000..1a59d7c Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-36-black.png differ diff --git a/dibs-web/public/stylesheets/images/icons-36-white.png b/dibs-web/public/stylesheets/images/icons-36-white.png new file mode 100644 index 0000000..5647bdc Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-36-white.png differ diff --git a/dibs-web/public/upload.html b/dibs-web/public/upload.html new file mode 100644 index 0000000..fb2ffb0 --- /dev/null +++ b/dibs-web/public/upload.html @@ -0,0 +1,97 @@ + + + + + + +
    + + +
    + + + + + diff --git a/dibs-web/script/rails b/dibs-web/script/rails new file mode 100755 index 0000000..f8da2cf --- /dev/null +++ b/dibs-web/script/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +APP_PATH = File.expand_path('../../config/application', __FILE__) +require File.expand_path('../../config/boot', __FILE__) +require 'rails/commands' diff --git a/doc/DIBS_Advanced_Guide.pdf b/doc/DIBS_Advanced_Guide.pdf new file mode 100644 index 0000000..ae15e40 Binary files /dev/null and b/doc/DIBS_Advanced_Guide.pdf differ diff --git a/doc/Tizen_SDK_Development_Guide.pdf b/doc/Tizen_SDK_Development_Guide.pdf new file mode 100644 index 0000000..f39ba84 Binary files /dev/null and b/doc/Tizen_SDK_Development_Guide.pdf differ diff --git a/doc/Tizen_SDK_Package_Guide.pdf b/doc/Tizen_SDK_Package_Guide.pdf new file mode 100644 index 0000000..b9d966e Binary files /dev/null and b/doc/Tizen_SDK_Package_Guide.pdf differ diff --git a/package/build.linux b/package/build.linux index 7ff849a..8264341 100755 --- a/package/build.linux +++ b/package/build.linux @@ -15,20 +15,12 @@ build() # install install() { - BIN_DIR=$SRCDIR/package/dibs.package.${BUILD_TARGET_OS}/data/dev_tools - DOC_DIR=$SRCDIR/package/dibs.package.${BUILD_TARGET_OS}/data/dev_tools/doc + BIN_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/tools/dibs/ mkdir -p $BIN_DIR - mkdir -p $DOC_DIR cp -f $SRCDIR/pkg-* $BIN_DIR/ cp -f $SRCDIR/build-* $BIN_DIR/ cp -rf $SRCDIR/src $BIN_DIR/ - cp -rf $SRCDIR/src $BIN_DIR/ - cp -f $SRCDIR/AUTHORS $DOC_DIR/ - cp -f $SRCDIR/LICENSE $DOC_DIR/ - cp -f $SRCDIR/NOTICE $DOC_DIR/ + cp -rf $SRCDIR/dibs-web $BIN_DIR/ + cp -f $SRCDIR/upgrade $BIN_DIR/ + echo $VERSION > $BIN_DIR/VERSION } - - -$1 -echo "$1 success" - diff --git a/package/build.macos b/package/build.macos new file mode 100755 index 0000000..8264341 --- /dev/null +++ b/package/build.macos @@ -0,0 +1,26 @@ +#!/bin/sh -xe +# clean +clean() +{ + rm -rf $SRCDIR/*.zip + rm -rf $SRCDIR/*.tar.gz +} + +# build +build() +{ + echo "build" +} + +# install +install() +{ + BIN_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/tools/dibs/ + mkdir -p $BIN_DIR + cp -f $SRCDIR/pkg-* $BIN_DIR/ + cp -f $SRCDIR/build-* $BIN_DIR/ + cp -rf $SRCDIR/src $BIN_DIR/ + cp -rf $SRCDIR/dibs-web $BIN_DIR/ + cp -f $SRCDIR/upgrade $BIN_DIR/ + echo $VERSION > $BIN_DIR/VERSION +} diff --git a/package/build.windows b/package/build.windows new file mode 100755 index 0000000..8264341 --- /dev/null +++ b/package/build.windows @@ -0,0 +1,26 @@ +#!/bin/sh -xe +# clean +clean() +{ + rm -rf $SRCDIR/*.zip + rm -rf $SRCDIR/*.tar.gz +} + +# build +build() +{ + echo "build" +} + +# install +install() +{ + BIN_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/tools/dibs/ + mkdir -p $BIN_DIR + cp -f $SRCDIR/pkg-* $BIN_DIR/ + cp -f $SRCDIR/build-* $BIN_DIR/ + cp -rf $SRCDIR/src $BIN_DIR/ + cp -rf $SRCDIR/dibs-web $BIN_DIR/ + cp -f $SRCDIR/upgrade $BIN_DIR/ + echo $VERSION > $BIN_DIR/VERSION +} diff --git a/package/changelog b/package/changelog new file mode 100644 index 0000000..2ccd4aa --- /dev/null +++ b/package/changelog @@ -0,0 +1,109 @@ +* 2.0.10 +- hot fix No method error +== hyoun jiil 2013-01-23 +* 2.0.9 +- several bug fix +-- sync bug fix +== hyoun jiil 2013-01-21 +* 2.0.8 +- WEB +-- Update new job list and job's status in JOBS page. +-- Update added job log and job's status in JOBS LOG page. +== sungmin kim 2012-12-12 +* 2.0.7 +- several bug fix +- Add distribution to upgrade commnad +- WEB +-- Fixed bug about request url include dot +-- Support browser about IE9 +-- Add loading event (spinner) +== hyoun jiil 2012-12-24 +* 2.0.6 +- several internal bug fix +== hyoun jiil 2012-12-24 +* 2.0.5 +- Upgraded protocol version to 1.7.0 +- Fixed Sign Up bug on WEB +- Fixed Job group filtering on WEB +- Fixed User Delete on WEB +== donghee yang 2012-12-14 +* 2.0.4 +- Fixed below bug again +== donghee yang 2012-12-12 +* 2.0.3 +- fixed bug about web, build-cli query +== donghee yang 2012-12-12 +* 2.0.2 +- fixed bug about web, build-cli query +== sungmin kim 2012-12-12 +* 2.0.1 +- fixed build.os +== sungmin kim 2012-12-12 +* 2.0.0 +- DIBS web added. +== sungmin kim 2012-12-12 +* 1.2.20 +- display distribution when query +== hyoun jiil 2012-11-29 +* 1.2.19 +- Fixed remote build bug and undefined method bug +== donghee yang 2012-11-29 +* 1.2.18 +- Fixed "cancel" operation of remote job +== donghee yang 2012-11-29 +* 1.2.17 +- change dir seperator when windows remove script execute +== hyoun jiil 2012-11-28 +* 1.2.16 +- Increased communication timeout to 120sec +== donghee yang 2012-11-28 +* 1.2.15 +- Increased communication timeout to 60sec +== donghee yang 2012-11-28 +* 1.2.14 +- Applied basic job priority +- Old job directory will be cleaned when restart +== donghee yang 2012-11-28 +* 1.2.13 +- multi-build can passing --noreverse option +== hyoun jiil 2012-10-29 +* 1.2.12 +- Change log on working package server +== hyoun jiil 2012-10-29 +* 1.2.10 +- Change log support +== hyoun jiil 2012-10-29 +* 1.2.9 +- Added distribution lock +== hyoun jiil 2011-10-18 +* 1.2.8 +- Fixed "cancel" bug +- Changed to remain logss about communication errors +== hyoun jiil 2011-10-18 +* 1.2.7 +- Fixed a bug that reverse build choose wrong distribution project +== hyoun jiil 2011-10-17 +* 1.2.6 +- Increase TimeOut to 30 sec +== hyoun jiil 2011-10-17 +* 1.2.5 +- Fixed a bug that pkg-build is not working +- Fixed some bugs when using ruby1.9.1 +== hyoun jiil 2011-10-17 +* 1.2.4 +- Fixed a bug that "upgrade" of sub servers are not done +== hyoun jiil 2011-10-16 +* 1.2.3 +- Set "wget" retry count to 3 +== hyoun jiil 2011-10-16 +* 1.2.2 +- Fixed server log contents +== hyoun jiil 2011-10-16 +* 1.2.1 +- Fixed some bugs : upgrade, parse error handling, pkg-build, remote job cancel +== hyoun jiil 2011-10-16 +* 1.2.0 +- change log support +- db support +- multiple distribution support +== hyoun jiil 2012-10-16 diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index 3e172a3..60bd43c 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,15 +1,8 @@ -Package : dibs -Version : 0.20.7 -Maintainer : taejun ha, jiil hyoun , , donghee yang< donghee.yang@samsung.com > -Description : Distribute Inteligent Build System -OS : linux -Build-host-os : linux Source : dibs +Version :2.0.10 +Maintainer : taejun ha, jiil hyoun , donghyuk yang , donghee yang , sungmin kim , jiil hyoun , , donghee yang< donghee.yang@samsung.com > +OS : ubuntu-32, ubuntu-64, windows-32, windows-64, macos-64 +Build-host-os : ubuntu-32 Description : Distribute Inteligent Build System -OS : windows -Build-host-os : linux -Source : dibs diff --git a/package/pkginfo.manifest.local b/package/pkginfo.manifest.local new file mode 100644 index 0000000..ce655de --- /dev/null +++ b/package/pkginfo.manifest.local @@ -0,0 +1,6 @@ +Include: pkginfo.manifest + +Package : dibs +OS : ubuntu-32, windows-32, macos-64, ubuntu-64, windows-64 +Build-host-os : windows-32, macos-64, ubuntu-64, windows-64 +Description : Distribute Inteligent Build System diff --git a/pkg-build b/pkg-build index 22b58f3..dbfad26 100755 --- a/pkg-build +++ b/pkg-build @@ -1,7 +1,7 @@ -#!/usr/bin/ruby +#!/usr/bin/ruby =begin - + pkg-build Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -36,51 +36,59 @@ require "packageServer" require "Builder" require "optionparser" -option = parse +begin + option = parse +rescue => e + puts e.message + exit 0 +end #generate server when local package server is not set +# check HOST OS +if not Utils.check_host_OS() then + puts "Error: Your host OS is not supported!" + exit 1 +end + # if "--os" is not specified, use host os type if option[:os].nil? then option[:os] = Utils::HOST_OS -else - if not option[:os] =~ /^(linux|windows|darwin)$/ then - puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS " - exit 1 - end end path = Dir.pwd -if not File.exist? "package" then - puts "current dirctory \"#{path}\" is not package root directory" - exit 1 -end +if not File.exist? "package" then + puts "current dirctory \"#{path}\" is not package root directory" + exit 1 +end # if url specified if not option[:url].nil? then begin - builder = Builder.get("default") + builder = Builder.get("default") if builder.pkgserver_url != option[:url] then puts "Package server URL has been changed! Creating new builder..." - builder = Builder.create("default", option[:url], nil) + builder = Builder.create("default", option[:url], nil, nil, nil) end rescue puts "Default builder does not exist! Creating new builder..." - builder = Builder.create("default", option[:url], nil) + builder = Builder.create("default", option[:url], nil, nil, nil) end else # if url is not specified - begin - builder = Builder.get("default") + begin + builder = Builder.get("default") rescue puts "Default builder does not exist! Creating new builder..." - builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil) + builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil, nil, nil) end -end +end #build project -if not builder.build( Utils::WORKING_DIR, option[:os], option[:clean], option[:rev], [], []) then +if not builder.build( Utils::WORKING_DIR, option[:os], option[:clean], [], true) then puts "Build Failed!" + exit 1 else puts "Build Succeeded!" + exit 0 end diff --git a/pkg-clean b/pkg-clean index de48dce..6a6cbb4 100755 --- a/pkg-clean +++ b/pkg-clean @@ -1,7 +1,7 @@ -#!/usr/bin/ruby +#!/usr/bin/ruby =begin - + pkg-clean Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -37,20 +37,26 @@ require "Builder" require "CleanOptionParser" path = Dir.pwd -if not File.exist? "package" then - puts "current dirctory \"#{path}\" is not package root directory" - exit 1 -end +if not File.exist? "package" then + puts "current dirctory \"#{path}\" is not package root directory" + exit 1 +end option = parse #generate server when local package server is not set -begin - builder = Builder.get("default") +# check HOST OS +if not Utils.check_host_OS() then + puts "Error: Your host OS is not supported!" + exit 1 +end + +begin + builder = Builder.get("default") rescue puts "Default builder does not exist! Creating new builder..." - builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil) + builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil) end #build project diff --git a/pkg-cli b/pkg-cli index 2e0f21e..f2d2e8b 100755 --- a/pkg-cli +++ b/pkg-cli @@ -1,7 +1,7 @@ -#!/usr/bin/ruby +#!/usr/bin/ruby =begin - + pkg-cli Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -42,137 +42,119 @@ require "packageServer" #set global variable @WORKING_DIR = nil -$log = Logger.new('.log', 'monthly') - -#option parsing +#option parsing begin option = option_parse rescue => e # if option parse error print help message - $log.error "option parsing error" - system "#{__FILE__} help" + puts e.message exit 0 end +# check HOST OS +if not Utils.check_host_OS() then + puts "Error: Your host OS is not supported!" + exit 1 +end #if "--os" is not specfied, use host os type if option[:os].nil? then - system_type = `uname -s` - case system_type.strip - when "Linux" then - option[:os] = "linux" - when /MINGW32.*/ then - option[:os] = "windows" - when "Darwin" then - option[:os] = "darwin" - else - raise RuntimeError, "Unknown OS type : #{system_type}" - end + option[:os] = Utils::HOST_OS end -case option[:cmd] +case option[:cmd] when "update" then - client = Client.new( option[:url], nil, nil ) - client.update() + client = Client.new( option[:url], nil, nil ) + #client.update() when "clean" then - client = Client.new( nil, option[:loc], nil ) - client.clean(option[:f]) + client = Client.new( nil, option[:loc], nil ) + client.clean(option[:f]) when "download" then - client = Client.new( option[:url], option[:loc], nil ) - if not option[:url].nil? then - client.update() - end + client = Client.new( option[:url], option[:loc], nil ) + #if not option[:url].nil? then + # client.update() + #end file_loc = client.download( option[:pkg], option[:os], option[:t] ) -when "upload" then - client = Client.new( nil, nil, nil ) - result = client.upload( option[:alias], option[:id], option[:binpkg], option[:srcpkg], false ) - if not result.nil? then - puts result - end -when "source" then - client = Client.new( option[:url], option[:loc], nil ) - if not option[:url].nil? then - client.update() - end - client.download_source( option[:pkg], option[:os] ) when "install" then - client = Client.new( option[:url], option[:loc], nil ) - if not option[:url].nil? then - client.update() - end - client.install( option[:pkg], option[:os], option[:t], option[:f] ) + client = Client.new( option[:url], option[:loc], nil ) + #if not option[:url].nil? then + # client.update() + #end + client.install( option[:pkg], option[:os], option[:t], option[:f] ) when "install-file" then - client = Client.new( nil, option[:loc], nil ) - client.install_local_pkg( option[:pkg], option[:f] ) + client = Client.new( option[:url], option[:loc], nil ) + client.install_local_pkg( option[:pkg], option[:t], option[:f] ) when "uninstall" then - client = Client.new( nil, option[:loc], nil ) - client.uninstall( option[:pkg], option[:t] ) + client = Client.new( nil, option[:loc], nil ) + client.uninstall( option[:pkg], option[:t] ) when "upgrade" then - client = Client.new( option[:url], option[:loc], nil ) - if not option[:url].nil? then - client.update() - end - client.upgrade( option[:os], option[:t] ) + client = Client.new( option[:url], option[:loc], nil ) + #if not option[:url].nil? then + # client.update() + #end + client.upgrade( option[:os], option[:t] ) when "check-upgrade" then - client = Client.new( option[:url], option[:loc], nil ) - if not option[:url].nil? then - client.update() - end - client.check_upgrade( option[:os] ) + client = Client.new( option[:url], option[:loc], nil ) + #if not option[:url].nil? then + # client.update() + #end + client.check_upgrade( option[:os] ) when "show-rpkg" then - client = Client.new( option[:url], nil, nil ) - if not option[:url].nil? then - client.update() - end - puts client.show_pkg_info( option[:pkg], option[:os] ) + client = Client.new( option[:url], nil, nil ) + #if not option[:url].nil? then + # client.update() + #end + puts client.show_pkg_info( option[:pkg], option[:os] ) when "list-rpkg" then - client = Client.new( option[:url], nil, nil ) - if not option[:url].nil? then - client.update() - end + client = Client.new( option[:url], nil, nil ) + #if not option[:url].nil? then + # client.update() + #end result = client.show_pkg_list( option[:os] ) - if not result.nil? and not result.empty? then - result.each do |i| - name = i[0].strip - version = i[1].strip - desc = i[2].strip - puts name + " (" + version + ")" - end - end + if not result.nil? and not result.empty? then + result.each do |i| + name = i[0].strip + version = i[1].strip + desc = i[2].strip + puts name + " (" + version + ")" + end + end when "show-lpkg" then - client = Client.new( nil, option[:loc], nil ) - puts client.show_installed_pkg_info( option[:pkg] ) + client = Client.new( nil, option[:loc], nil ) + puts client.show_installed_pkg_info( option[:pkg] ) when "list-lpkg" then - client = Client.new( nil, option[:loc], nil ) + client = Client.new( nil, option[:loc], nil ) result = client.show_installed_pkg_list() - if not result.nil? and not result.empty? then - result.each do |i| - name = i[0].strip - version = i[1].strip - desc = i[2].strip - puts name + " (" + version + ")" - end - end + if not result.nil? and not result.empty? then + result.each do |i| + name = i[0].strip + version = i[1].strip + desc = i[2].strip + puts name + " (" + version + ")" + end + else + puts "Info: There is no any package." + end when "build-dep" then - client = Client.new( nil, nil, nil ) + client = Client.new( nil, nil, nil ) result = client.get_build_dependent_packages( option[:pkg], option[:os], true ) - ret = "" - result.each do |i| - ret = ret + i + " --> " - end - ret = ret.strip - ret[-3..-1] = "" - puts ret + ret = "" + result.each do |i| + ret = ret + i + " --> " + end + ret = ret.strip + ret[-3..-1] = "" + puts ret when "install-dep" then - client = Client.new( nil, nil, nil ) + client = Client.new( nil, nil, nil ) result = client.get_install_dependent_packages( option[:pkg], option[:os], true, false ) - ret = "" - result.each do |i| - ret = ret + i + " --> " - end - ret = ret.strip - ret[-3..-1] = "" - puts ret + ret = "" + result.each do |i| + ret = ret + i + " --> " + end + ret = ret.strip + ret[-3..-1] = "" + puts ret else - raise RuntimeError, "input option incorrect : #{option[:cmd]}" + raise RuntimeError, "Input is incorrect : #{option[:cmd]}" end diff --git a/pkg-svr b/pkg-svr index 3cf4121..6c50176 100755 --- a/pkg-svr +++ b/pkg-svr @@ -1,7 +1,7 @@ -#!/usr/bin/ruby +#!/usr/bin/ruby =begin - + pkg-svr Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -35,67 +35,84 @@ require "utils" require "packageServer" require "serverOptParser" -#option parsing +#option parsing begin option = option_parse rescue => e - puts "\n=============== Error occured ==============================" puts e.message - puts e.backtrace.inspect - puts "=============================================================\n" exit 0 end -begin +begin if option[:cmd].eql? "list" then if option[:id].empty? then - PackageServer.list_id + PackageServer.list_id else PackageServer.list_dist option[:id] - end - exit - end + end + exit + end server = PackageServer.new( option[:id] ) - if server.nil? + if server.nil? raise RuntimeError, "server class creation fail" end - case option[:cmd] - when "create" + case option[:cmd] + when "create" server.create( option[:id], option[:dist], option[:url], option[:loc] ) when "register" - server.register( option[:spkgs], option[:bpkgs], option[:dist], option[:gensnap], option[:test] ) + server.register( option[:pkgs], option[:dist], option[:gensnap], option[:test], false ) when "gen-snapshot" - server.generate_snapshot( option[:snap], option[:dist], option[:bsnap], option[:bpkgs] ) + server.generate_snapshot( option[:snaps][0], option[:dist], option[:bsnap] ) when "sync" - server.sync( option[:dist], option[:force] ) + server.sync( option[:dist], option[:force], option[:snaps][0] ) when "add-dist" server.add_distribution( option[:dist], option[:url], option[:clone] ) - when "spkg-path" - server.find_source_package_path( option[:dist], option[:spkgs] ) + when "add-os" + server.add_os( option[:dist], option[:os] ) when "remove" - puts "Do you want to really? then input \"YES\"" - input = $stdin.gets.strip - if input.eql? "YES" then - puts "Remove server!" - else - puts "Remove is canceled by user input" - exit(0) + if not option[:force] then + puts "Do you want to really? then input \"YES\"" + input = $stdin.gets.strip + if input.eql? "YES" then + puts "Remove server!" + else + puts "Remove is canceled by user input" + exit(0) + end + end + + server.remove_server() + when "remove-dist" + if not option[:force] then + puts "Do you want to really? then input \"YES\"" + input = $stdin.gets.strip + if input.eql? "YES" then + puts "Remove server!" + else + puts "Remove is canceled by user input" + exit(0) + end end - server.remove_server( option[:id] ) + server.remove_dist( option[:dist] ) when "remove-pkg" - server.remove_pkg( option[:id], option[:dist], option[:bpkgs] ) + server.remove_pkg( option[:dist], option[:pkgs], option[:os] ) + when "remove-snapshot" + server.remove_snapshot( option[:dist], option[:snaps] ) + when "clean" + server.clean( option[:dist], option[:snaps] ) + when "start" + server.start( option[:port], option[:passwd] ) + when "stop" + server.stop( option[:port], option[:passwd] ) else raise RuntimeError, "input option incorrect : #{option[:cmd]}" end -rescue => e - puts "\n=============== Error occured ==============================" +rescue => e puts e.message - puts e.backtrace.inspect - puts "=============================================================\n" end diff --git a/src/build_server/BinaryUploadProject.rb b/src/build_server/BinaryUploadProject.rb new file mode 100644 index 0000000..f653b80 --- /dev/null +++ b/src/build_server/BinaryUploadProject.rb @@ -0,0 +1,200 @@ +=begin + + BinaryUploadProject.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +require 'dbi' +$LOAD_PATH.unshift File.dirname(__FILE__) +require "CommonProject.rb" +require "RegisterPackageJob.rb" +require "Version.rb" +require "PackageManifest.rb" + + +class BinaryUploadProject < CommonProject + attr_accessor :pkg_name + + # initialize + def initialize( name, server, os_list, dist_name, pkg_name = nil ) + super(name, "BINARY", server, os_list, dist_name) + @pkg_name = pkg_name + end + + + # create new job + def create_new_job( filename, dock = "0" ) + file_path = "#{@server.transport_path}/#{dock}/#{filename}" + new_job = create_new_job_from_local_file( file_path ) + if not new_job.nil? then + new_job.set_auto_remove(true) + end + + return new_job + end + + + def create_new_job_from_local_file( file_path ) + filename = File.basename(file_path) + new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + pkg_name = new_name.split(",")[0] + os = new_name.split(",")[2] + + # check file name + if @pkg_name != pkg_name then + @server.log.error( "registed name is #{@pkg_name} not #{pkg_name} !", Log::LV_USER) + return nil + end + + # check os name + if not @server.supported_os_list.include? os then + @server.log.error( "server not support OS : #{os}", Log::LV_USER) + return nil + end + + # check package info + if not File.exist? file_path then + @server.log.error( "file not exists in #{file_path}", Log::LV_USER) + return nil + end + + pkginfo_dir = "#{@path}/pkginfos" + if not File.exist? pkginfo_dir then FileUtils.mkdir_p pkginfo_dir end + if not Utils.extract_a_file(file_path, "pkginfo.manifest", pkginfo_dir) then + @server.log.error( "pkginfo.manifest file is not exist", Log::LV_USER) + return nil + end + begin + pkginfo =PackageManifest.new("#{pkginfo_dir}/pkginfo.manifest") + rescue => e + @server.log.error( e.message, Log::LV_USER) + return nil + end + + ##set up change log + #change_log = {} + #begin + # change_log = Parser.read_changelog "#{pkginfo_dir}/changelog" if File.exist? "#{pkginfo_dir}/changelog" + #rescue => e + # @server.log.error( e.message, Log::LV_USER) + # return nil + #end + + #if not change_log.empty? and pkginfo.packages[0].change_log.empty? then + # pkginfo.packages.each {|pkg| pkg.change_log = change_log} + #end + + #if @server.changelog_check and not pkginfo.packages[0].does_change_exist? then + # @server.log.error( "change log not found", Log::LV_USER) + # return nil + #end + + pkgs = pkginfo.get_target_packages(os) + if pkgs.count != 1 then + @server.log.error( "only one package can upload at one time", Log::LV_USER) + return nil + end + if pkgs[0].package_name != @pkg_name then + @server.log.error( "package name is #{pkgs[0].package_name} not #{@pkg_name}", Log::LV_USER) + return nil + end + + new_job = RegisterPackageJob.new( file_path, self, @server, nil, @dist_name ) + end + + + def self.create_table(db, post_fix) + db.do "CREATE TABLE project_bins ( + project_id INTEGER NOT NULL, + pkg_name VARCHAR(32) NOT NULL, + PRIMARY KEY ( project_id ), + CONSTRAINT fk_project_bins_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ) )#{post_fix}" + end + + + def self.load(name, dist_name, server, db) + row, prj_os_list, source_info, package_info = load_row(name, dist_name, db) + prj_id = row['id'] + prj_name = row['name'] + prj_passwd = row['password'] + + new_project = BinaryUploadProject.new(prj_name, server, prj_os_list, dist_name) + if not prj_passwd.empty? then new_project.passwd = prj_passwd end + new_project.set_project_id( prj_id ) + new_project.set_source_info( source_info ) + new_project.set_package_info( package_info ) + + row=db.select_one("SELECT * FROM project_bins WHERE project_id=#{prj_id}") + if row.nil? then return nil end + new_project.pkg_name=row['pkg_name'] + + return new_project + end + + + def save(db) + is_new = save_common(db) + init() + + if is_new then + db.do "INSERT INTO project_bins VALUES (#{@prj_id},'#{@pkg_name}')" + db.do "INSERT INTO group_project_accesses + VALUES ( (SELECT groups.id FROM groups WHERE groups.name = 'admin'),'#{@prj_id}','TRUE')" + else + db.do "UPDATE project_bins SET pkg_name='#{@pkg_name}' WHERE project_id=#{@prj_id})" + end + end + + + def save_source_info(ver,info) + @server.get_db_connection() do |db| + save_source_info_internal(ver,info, db) + end + end + + + # save package info + def save_package_info_from_manifest(version, file_path, os) + begin + pkginfo =PackageManifest.new(file_path) + rescue => e + @server.log.error e.message + return + end + + pkginfo.get_target_packages(os).each do |pkg| + save_package_info(pkg.version, pkg.package_name, os) + end + end + + + def unload(db) + unload_common(db) + if @prj_id != -1 then + db.do "DELETE FROM project_bins WHERE project_id=#{@prj_id}" + end + end +end diff --git a/src/build_server/BuildClientOptionParser.rb b/src/build_server/BuildClientOptionParser.rb index 79941ca..63fb3da 100644 --- a/src/build_server/BuildClientOptionParser.rb +++ b/src/build_server/BuildClientOptionParser.rb @@ -1,6 +1,6 @@ =begin - - BuildClientOptionParser.rb + + BuildClientOptionParser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -26,72 +26,204 @@ Contributors: - S-Core Co., Ltd =end +$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common" require 'optparse' +require 'utils' + +class BuildClientUsage + BUILD="build-cli build -N -d [-o ] [-w ] [--async] [-D ] [-U user-email] [-V]" + RESOLVE="build-cli resolve -N -d [-o ] [-w ] [--async] [-D ] [-U user-email] [-V]" + QUERY="build-cli query -d " + QUERY_SYSTEM="build-cli query-system -d " + QUERY_PROJECT="build-cli query-project -d " + QUERY_JOB="build-cli query-job -d " + CANCEL="build-cli cancel -j -d [-w ] [-U user-email]" + REGISTER="build-cli register -P -d [-t ] [-w ] [-D ] [-U user-email]" +end + + +def option_error_check( options ) + case options[:cmd] + + when "build" then + if options[:project].nil? or options[:project].empty? or + options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::BUILD + end + + when "resolve" then + if options[:project].nil? or options[:project].empty? or + options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::RESOLVE + end + + when "query" then + if options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::QUERY + end + + when "query-system" then + if options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::QUERY_SYSTEM + end + + when "query-project" then + if options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::QUERY_PROJECT + end + + when "query-job" then + if options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::QUERY_JOB + end -def option_parse - options = {} - banner = "Usage: build-cli {build|resolve|query} ..." + "\n" \ - + "\t" + "build-cli build -g -c [-d ] [-p ] [-o ] [-a ] " + "\n" \ - + "\t" + "build-cli resolve -g -c [-d ] [-p ] [-o ] [-a ] " + "\n" \ - + "\t" + "build-cli query [-d ] [-p ] [-o ] " + "\n" - - optparse = OptionParser.new do|opts| - # Set a banner, displayed at the top - # of the help screen. - - opts.banner = banner - - opts.on( '-g', '--git ', 'git repository' ) do|git| - options[:git] = git - end - - opts.on( '-c', '--commit ', 'git commit id/tag' ) do|git| - options[:commit] = git - end - - options[:domain] = nil - opts.on( '-d', '--domain ', 'remote build server ip address. default 172.21.111.177' ) do|domain| - options[:domain] = domain - end - - options[:port] = nil - opts.on( '-p', '--port ', 'remote build server port. default 2222' ) do|port| - options[:port] = port - end - - options[:os] = nil - opts.on( '-o', '--os ', 'target operating system linux/windows/darwin' ) do|os| - options[:os] = os - end - - options[:async] = "NO" - opts.on( '-a', '--async', 'asynchronous job' ) do - options[:async] = "YES" - end - - opts.on( '-h', '--help', 'display this information' ) do - puts opts + when "cancel" then + if options[:job].nil? or options[:job].empty? or + options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::CANCEL + end + when "register" then + if options[:package].nil? or options[:package].empty? or + options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildClientUsage::REGISTER + end + + else + raise ArgumentError, "Input is incorrect : #{options[:cmd]}" + end + + if ARGV.length > 1 then + raise ArgumentError, "Unknown argument value : #{ARGV[1]}" + end +end + +def option_parse + options = {} + banner = "Requiest service to build-server command-line tool." + "\n" \ + + "\n" + "Usage: build-cli [OPTS] or build-cli (-h|-v)" + "\n" \ + + "\n" + "Subcommands:" + "\n" \ + + "\t" + "build Build and create package." + "\n" \ + + "\t" + "resolve Request change to resolve-status for build-conflict." + "\n" \ + + "\t" + "query Query information about build-server." + "\n" \ + + "\t" + "query-system Query system information about build-server." + "\n" \ + + "\t" + "query-project Query project information about build-server." + "\n" \ + + "\t" + "query-job Query job information about build-server." + "\n" \ + + "\t" + "cancel Cancel a building project." + "\n" \ + + "\t" + "register Register the package to the build-server." + "\n" \ + + "\n" + "Subcommand usage:" + "\n" \ + + "\t" + BuildClientUsage::BUILD + "\n" \ + + "\t" + BuildClientUsage::RESOLVE + "\n" \ + + "\t" + BuildClientUsage::QUERY + "\n" \ + + "\t" + BuildClientUsage::QUERY_SYSTEM + "\n" \ + + "\t" + BuildClientUsage::QUERY_PROJECT + "\n" \ + + "\t" + BuildClientUsage::QUERY_JOB + "\n" \ + + "\t" + BuildClientUsage::CANCEL + "\n" \ + + "\t" + BuildClientUsage::REGISTER + "\n" \ + + "\n" + "Options:" + "\n" + + optparse = OptionParser.new(nil, 32, ' '*8) do|opts| + + # Set a banner, displayed at the top + # of the help screen. + + opts.banner = banner + + opts.on( '-N', '--project ', 'project name' ) do|project| + if not Utils.multi_argument_test( project, "," ) then + raise ArgumentError, "Project variable parsing error : #{project}" + end + options[:project] = project + end + + options[:domain] = nil + opts.on( '-d', '--address ', 'build server address: 127.0.0.1:2224' ) do|domain| + options[:domain] = domain + end + + options[:os] = nil + opts.on( '-o', '--os ', 'target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64' ) do |os| + if not Utils.multi_argument_test( os, "," ) then + raise ArgumentError, "OS variable parsing error : #{os}" + end + options[:os] = os + end + + options[:async] = "NO" + opts.on( '--async', 'asynchronous job' ) do + options[:async] = "YES" + end + + options[:noreverse] = "NO" + opts.on( '--noreverse', 'do not check reverse build' ) do + options[:noreverse] = "YES" + end + + opts.on( '-j', '--job ', 'job number' ) do|job| + options[:job] = job + end + + options[:passwd] = "" + opts.on( '-w', '--passwd ', 'password for managing project' ) do|passwd| + options[:passwd] = passwd + end + + opts.on( '-P', '--pkg ', 'package file path' ) do|package| + options[:package] = package.strip + end + + opts.on( '-D', '--dist ', 'distribution name' ) do|dist| + options[:dist] = dist + end + + opts.on( '-t', '--ftp ', 'ftp server url: ftp://dibsftp:dibsftp@127.0.0.1' ) do|domain| + options[:fdomain] = domain + end + + options[:user] = "admin@user" + opts.on( '-U', '--user ', 'user email infomation' ) do|user| + options[:user] = user + end + + options[:verbose] = "NO" + opts.on( '-V', '--verbose', 'verbose mode' ) do + options[:verbose] = "YES" + end + + opts.on( '-h', '--help', 'display help' ) do + opts.help.split("\n").each {|op| puts op if not op.include? "--noreverse"} exit - end - - end - - cmd = ARGV[0] + end - if cmd.eql? "build" or cmd.eql? "resolve" or cmd.eql? "query" or - cmd =~ /(help)|(-h)|(--help)/ then + opts.on( '-v', '--version', 'display version' ) do + puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version() + exit + end - if cmd.eql? "help" then - ARGV[0] = "-h" + end + + cmd = ARGV[0] + + if cmd.eql? "build" or cmd.eql? "resolve" or + cmd.eql? "query" or cmd.eql? "query-system" or + cmd.eql? "query-project" or cmd.eql? "query-job" or + cmd.eql? "cancel" or + cmd.eql? "register" or + cmd =~ /(-v)|(--version)/ or + cmd =~ /(help)|(-h)|(--help)/ then + + if cmd.eql? "help" then + ARGV[0] = "-h" end - options[:cmd] = ARGV[0] - else - raise ArgumentError, banner - end + options[:cmd] = ARGV[0] + else + raise ArgumentError, "Usage: build-cli [OPTS] or build-cli -h" + end + + optparse.parse! + + option_error_check options - optparse.parse! - - return options -end + return options +end diff --git a/src/build_server/BuildJob.rb b/src/build_server/BuildJob.rb index 2a7f5c7..71c3485 100644 --- a/src/build_server/BuildJob.rb +++ b/src/build_server/BuildJob.rb @@ -1,5 +1,5 @@ =begin - + BuildJob.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -35,89 +35,360 @@ require "client.rb" require "PackageManifest.rb" require "Version.rb" require "Builder.rb" -require "BuildServer.rb" +require "RemoteBuilder.rb" require "JobLog.rb" require "mail.rb" +require "utils.rb" +require "ReverseBuildChecker.rb" +require "CommonJob.rb" -class BuildJob +class BuildJob < CommonJob - attr_accessor :blocked_by + attr_accessor :pkginfo, :source_path + attr_accessor :pkgsvr_client, :thread + attr_accessor :rev_fail_projects, :rev_success_jobs + attr_accessor :pending_ancestor, :cancel_state + attr_accessor :no_reverse + attr_accessor :remote_id # initialize - def initialize () - @blocked_by = [] + def initialize (project, os, server) + super(server) + @project = project + @os = os + @type = "BUILD" + + @cancel_state = "NONE" + @resolve = false + @host_os = Utils::HOST_OS + if not @server.distmgr.nil? then + @pkgsvr_url = @server.distmgr.get_distribution(project.dist_name).pkgsvr_url + @pkgsvr_ip = @server.distmgr.get_distribution(project.dist_name).pkgsvr_ip + @pkgsvr_port = @server.distmgr.get_distribution(project.dist_name).pkgsvr_port + else + @pkgsvr_url = "" + @pkgsvr_ip = "" + @pkgsvr_port = "" + end + @job_root = "#{@server.path}/jobs/#{@id}" + @source_path = @job_root+"/temp" + @job_working_dir=@job_root+"/works" + @buildroot_dir = "#{@job_root}/buildroot" + + # this item will be initialized on pre-verify + @pkginfo = nil + @pkgsvr_client = nil + @thread = nil + @log = nil + @parent = nil # for job hierachy + + #for cancel operation + @pending_ancestor = nil # for cancel pending job + @remote_id = nil # for cancel remote_working job + @build_dep_prjs = nil # for cacnel pending job + + # for resolving build-break + @rev_fail_projects = [] # list of [project,os] + @rev_success_jobs = [] # list of job + + # remote build + @remote_server = nil + + # job type + @is_rev_build_check_job = false + @is_remote_job = false + + # for internal(transferred) job + @is_internal_job = false + @dock_num = "0" + + @external_pkgs = [] + @force_rebuild = false + + @no_reverse = false end - # execute - def execute - @log.info( "Invoking a thread for building Job #{@id}", Log::LV_USER) - if @status == "ERROR" then return end - @thread = Thread.new { - # main - thread_main() - - # close - terminate() - } + + def get_distribution_name() + return @project.dist_name + end + + + def get_buildroot() + return @buildroot_dir + end + + + # set reverse build check job + def set_rev_build_check_job( parent ) + @is_rev_build_check_job = true + + # if parent exists, share build-root + if not parent.nil? then + set_parent_job( parent ) + end + end + + + def is_rev_build_check_job() + return @is_rev_build_check_job + end + + + def set_remote_job(server) + @is_remote_job = true + @remote_server=server + end + + + def get_remote_server() + return @remote_server + end + + + def set_no_reverse() + @no_reverse = true + end + + + def set_internal_job( dock_num ) + @is_internal_job = true + @dock_num = dock_num + end + + + # set option for waiting for resolve + def set_resolve_flag() + @resolve = true + end + + + # set force rebuild + # This make project to build + # even though there is a package of same version on pkg-server + def set_force_rebuild(value) + @force_rebuild = value end - # remote - def execute_remote(server) - @log.info( "Invoking a thread for remote-building Job #{@id}", Log::LV_USER) - if @status == "ERROR" then return end - @thread = Thread.new { - # main - remote_thread_main( server ) - - # close - terminate() - } + # add external packages to overwrite before build + def add_external_package( file_name ) + @external_pkgs.push "#{@job_root}/external_pkgs/#{file_name}" + end + + + #terminate + def terminate() + #do noting + end + + + #cancel + def cancel() + # kill sub process if exist? + kill_sub_process() + + # cancel all its reverse job + @server.jobmgr.reverse_build_jobs.each do |job| + if job.get_parent_job() == self and job.cancel_state == "NONE" then + job.cancel_state = "INIT" + end + end + + # cancel log print + if not @log.nil? then + @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER) + end + + case @status + when "REMOTE_WORKING" then + client = BuildCommClient.create( @remote_server.ip, @remote_server.port, @log ) + if not client.nil? then + client.send "CANCEL|#{@remote_id}|#{self.get_project.passwd}|admin@user" + result1 = client.receive_data() + if result1.nil? then + @log.info( "cancel operation failed [connection error] !!", Log::LV_USER) + else + result1.each do |l| + @log.info(l, Log::LV_USER) + end + end + client.terminate + end + when "PENDING" then + if @pending_ancestor.nil? then + #resolve pending job + pending_descendants = @server.jobmgr.jobs.select do |j| + (not j.pending_ancestor.nil?) and "#{j.pending_ancestor.id}" == "#{@id}" + end + pending_descendants.each do |pd| + pd.cancel_state = "INIT" + end + else + # remove myself from success job if exist + # and add myself into rev_fail_project list if not exist + @pending_ancestor.remove_rev_success_job(self) + @pending_ancestor.add_rev_fail_project( @project, @os ) + + # remove the project that depends on me if exist + # and add it into rev_fail_project list if not exist + p_sub_jobs = @server.jobmgr.jobs.select do |j| + ( not j.pending_ancestor.nil? and + "#{j.pending_ancestor.id}" == "#{@pending_ancestor.id}" and + j.is_build_dependent_project(@project, @os) ) + end + p_sub_jobs.each do |d| + @pending_ancestor.remove_rev_success_job(d) + @pending_ancestor.add_rev_fail_project( d.get_project, d.os ) + + if not d.thread.nil? then d.thread.terminate end + d.status = "WAITING" + end + end + when "WORKING", "WAITING" , "INITIALIZING" , "JUST_CREATED" then + #just log + else # ERROR | FINISHED | RESOLVED + #do noting + end end # check building is possible def can_be_built_on?(host_os) - for pkg in @pkginfo.packages - if pkg.os == @os and pkg.build_host_os.include? host_os then + if @pkginfo.nil? then return false end + + @pkginfo.packages.each do |pkg| + if pkg.os_list.include? @os and pkg.build_host_os.include? host_os then return true end end - return false end + def get_packages() + return @pkginfo.packages + end + + + def get_build_dependencies(target_os) + return @pkginfo.get_build_dependencies(target_os) + end + + + def get_source_dependencies(target_os,host_os) + return @pkginfo.get_source_dependencies(target_os,host_os) + end + + + def is_compatible_with?(o) + # must have same distribution + if get_distribution_name() != o.get_distribution_name() then + return false + end + + if type != o.type then return false end + + my_project = get_project() + other_project = o.get_project() + + # check project name + if my_project.nil? or other_project.nil? or + my_project.name != other_project.name then + return false + end + + # check version + if @pkginfo.nil? or o.pkginfo.nil? or + not(Version.new(@pkginfo.get_version()) == Version.new(o.pkginfo.get_version())) then + return false + end + + # check compat os + @pkginfo.get_target_packages(@os).each do |p| + if not p.os_list.include?(o.os) then return false end + end + + return true + end + + + def has_build_dependency?(other_job) + + if has_same_packages?(other_job) or + does_depend_on?(other_job) or + does_depended_by?(other_job) then + + return true + else + return false + end + end + + def has_same_packages?( wjob ) - for pkg in @pkginfo.packages - for wpkg in wjob.pkginfo.packages + + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + # same package must have same os + if not @os.eql? wjob.os then + return false + end + + # check package name + get_packages().each do |pkg| + wjob.get_packages().each do |wpkg| if pkg.package_name == wpkg.package_name then #puts "Removed from candiated... A == B" return true end end end + return false end def does_depend_on?( wjob ) - for dep in @pkginfo.get_build_dependencies(@os, BuildServer::HOST_OS) - for wpkg in wjob.pkginfo.packages - if dep.package_name == wpkg.package_name then + + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + # compare build dependency + get_build_dependencies(@os).each do |dep| + wjob.get_packages().each do |wpkg| + # dep packages of my job must have same name and target os + # with packages in working job + if dep.package_name == wpkg.package_name and + dep.target_os_list.include? wjob.os then #puts "Removed from candiated... A -> B" return true end end end + return false end def does_depended_by?( wjob ) - for pkg in @pkginfo.packages - for dep in wjob.pkginfo.get_build_dependencies(@os, BuildServer::HOST_OS) - if pkg.package_name == dep.package_name then + + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + get_packages().each do |pkg| + wjob.get_build_dependencies(wjob.os).each do |dep| + # dep package of working job must have same name and target os + # with packages in my job + if dep.package_name == pkg.package_name and + dep.target_os_list.include? @os then #puts "Checking... A <- B" return true end @@ -128,89 +399,203 @@ class BuildJob def is_connected? + return @log.is_connected? + end + - # nil? then false - if @outstream.nil? then + # return the job is asyncronous job + def is_asynchronous_job? + if not @log.has_second_out? then + return true + else return false end + end - # send chk signal - begin - BuildCommServer.send_chk( @outstream ) - rescue - return false + + # remove job from reverse success job + def remove_rev_success_job( job ) + @rev_success_jobs.delete job if @rev_success_jobs.include? job + end + + + # check [project,os] is in reverse fail project list + def is_rev_fail_project( prj, os ) + # check the project already exist + @rev_fail_projects.each do |p| + if p[0] == prj and p[1] == os then + return true + end end - return true + return false end - # return the job is asyncronous job - def is_asynchronous_job? - if @outstream.nil? then - return true + # add [project,os] to reverse fail project list + def add_rev_fail_project( prj, os ) + # check the project already exist + @rev_fail_projects.each do |p| + if p[0] == prj and p[1] == os then + return + end + end + # if not, add it + @rev_fail_projects.push [prj,os] + end + + + # remove [project,os] from reverse fail project list + def remove_rev_fail_project( prj, os ) + remove_list = [] + + # check project and os name + @rev_fail_projects.each do |p| + if p[0] == prj and p[1] == os then + remove_list.push p + end + end + + # remove + remove_list.each do |r| + @rev_fail_projects.delete r + end + end + + + # get project that my job is dependent on + def get_build_dependent_projects() + if @build_dep_prjs.nil? then + deps = @pkginfo.get_build_dependencies(@os) + pkgs = deps.map do |x| + # if "os" is not specified, use my "os" + if x.target_os_list.nil? or x.target_os_list.empty? then + os = @os + else + os = x.target_os_list[0] + end + + # package as item + @pkgsvr_client.get_pkg_from_list(x.package_name, os) + end + prjs = @server.prjmgr.get_projects_from_pkgs(pkgs, get_distribution_name()) + @build_dep_prjs = prjs + end + + return @build_dep_prjs + end + + + # check if the project is my dependent project + def is_build_dependent_project( prj, os ) + dep_list = get_build_dependent_projects() + dep_list.each do |dep| + if dep[0] == prj and dep[1] == os then + return true + end + end + + return false + end + + + def progress + return "" + end + + + def get_log_url() + # only when server support log url + if @server.job_log_url.empty? then + return "","" + end + + url = "#{@server.job_log_url}/#{@id}/log" + # if remote, the file existence must be checked + if File.exist? "#{@job_root}/remote_log" then + return url,"#{@server.job_log_url}/#{@id}/remote_log" else - return false + return url,"" end end + + # # PROTECTED METHODS # - protected - # main module - def thread_main + # main module + protected + def job_main() + @log.info( "Invoking a thread for building Job #{@id}", Log::LV_USER) + if @status == "ERROR" then return end @log.info( "New Job #{@id} is started", Log::LV_USER) - - @status = "BUILDING" - - # update local package server - @server.local_pkgsvr.sync( @server.local_pkgsvr.get_default_dist_name(), false ) - - # checking version - if not check_package_version() - @status = "ERROR" - - return - end # checking build dependency - if not check_build_dependency() + if not @is_remote_job and not @is_internal_job and + not check_build_dependency() then + if @is_internal_job then copy_result_files_to_master() end @status = "ERROR" - return + return false end # clean build - if not build() + if not build() then + if @is_internal_job then copy_result_files_to_master() end + @status = "ERROR" - return + return false end # upload - if not upload() + if not @is_rev_build_check_job and not @is_internal_job and + @parent.nil? and + not upload() then @status = "ERROR" - return + return false end - + + # copy result files to transport path + if @is_internal_job then + copy_result_files_to_master() + elsif not @parent.nil? and not @is_rev_build_check_job then + copy_result_files(@parent.source_path) + end + # INFO. don't change this string @log.info( "Job is completed!", Log::LV_USER) @status = "FINISHED" + return true end # check if local package version is greater than server - def check_package_version() + def check_package_version( source_info ) @log.info( "Checking package version ...", Log::LV_USER) - # package update - @pkgsvr_client.update + # check if version is same and source_info is different + ver_local = @pkginfo.packages[0].version + old_source_info = @project.get_source_info( ver_local ) + if not old_source_info.nil? and old_source_info != source_info then + @log.error( "Source code has been changed without increasing version!", Log::LV_USER) + @log.error( " * Version : #{ver_local}", Log::LV_USER) + @log.error( " * Before : #{old_source_info}", Log::LV_USER) + @log.error( " * Current : #{source_info}", Log::LV_USER) - for pkg in @pkginfo.packages - ver_local = pkg.version - #ver_svr = @pkgsvr_client.get_package_version( pkg.package_name, @os ) - ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version") - if not ver_svr.nil? and Version.new(ver_local) <= Version.new(ver_svr) then + return false + end + + # compare with package version in package server + @pkginfo.packages.each do |pkg| + # check all supported os + ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version") + # ignore if package does not exist + if ver_svr.nil? then next end + + # compare version + if Version.new(ver_local) < Version.new(ver_svr) or + ( not @force_rebuild and Version.new(ver_local) == Version.new(ver_svr) ) then @log.error( "Version must be increased : #{ver_local} <= #{ver_svr}", Log::LV_USER) return false end @@ -221,193 +606,592 @@ class BuildJob # build dependency version + # make sure that package server has all dependency packages of job def check_build_dependency() @log.info( "Checking build dependency ...", Log::LV_USER) + @pkgsvr_client.update + unmet_bdeps = [] + @pkginfo.get_build_dependencies( @os ).each do |dep| + # if parent exist, search parent source path first + # if not found, check package server + ver_svr = nil + if not @parent.nil? then + local_pkg = get_local_path_of_dependency( dep, @parent ) + if not local_pkg.nil? then + ver_svr = Utils.get_version_from_package_file( local_pkg ) + else + ver_svr = nil + end + end + if not ver_svr.nil? then next end + + if not remote_package_of_dependency_exist?(dep) then + unmet_bdeps.push dep + end + end + + @log.info( "Checking install dependency ...", Log::LV_USER) + unmet_ideps = [] + @pkginfo.get_install_dependencies( @os ).each do |dep| + # if parent exist, search pkginfos for all sub jobs + # if not found, check package server + found = false + if not @parent.nil? and @parent.type == "MULTIBUILD" then + @parent.get_sub_jobs().each do |j| + os = (dep.target_os_list.empty?) ? @os : dep.target_os_list[0] + if j.pkginfo.pkg_exist?(dep.package_name, dep.base_version, os) then + found = true; break + end + end + end + if found then next end + + if not remote_package_of_dependency_exist?(dep) then + unmet_ideps.push dep + end + end + + # unmet dependencies found , report the errors + if not unmet_bdeps.empty? or not unmet_ideps.empty? then + @log.error( "Unmet dependency found!", Log::LV_USER) + unmet_bdeps.each do |d| + os = (d.target_os_list.empty?) ? @os : d.target_os_list[0] + @log.error( " * #{d.package_name}(#{os}) for build-dependency", Log::LV_USER) + end + unmet_ideps.each do |d| + os = (d.target_os_list.empty?) ? @os : d.target_os_list[0] + @log.error( " * #{d.package_name}(#{os}) for install-dependency", Log::LV_USER) + end + + return false + else + return true + end + end + + + # build clean + def build() - for dep in @pkginfo.get_build_dependencies( @os, @host_os ) - #ver_svr = @pkgsvr_client.get_package_version( dep.package_name, @os ) - if dep.target_os_list.count != 0 then - dep_target_os = dep.target_os_list[0] + # check there are pending packages which wait for me + # it will return nil if not exist + # this process must be skip if it is sub-job + if not @is_rev_build_check_job and not @is_internal_job then + @server.cancel_lock.synchronize do + @pending_ancestor = get_pending_ancestor_job() + end + end + + if not @pending_ancestor.nil? then + # resolve other pending job + resolve() + elsif @resolve then + # wait for being resolved by other jobs + # this condition must be placed after checking pending status + wait_resolve() + else + # build + build_normal() + end + end + + + # return pending job that wait for me + def get_pending_ancestor_job() + @server.jobmgr.get_pending_jobs.each do |job| + # must have same distribution + if get_distribution_name() != job.get_distribution_name() then + next + end + + if job.is_rev_fail_project(@project,@os) then + return job + end + end + + return nil + end + + + # check whether build this job or not + # if not build, then return its compat pkgs list + def check_compatable_packages + compat_pkgs = [] # [ package name, os, local_path ] + + @pkginfo.get_target_packages(@os).each do |p| + # if package has only os then must build + if p.os_list.count <= 1 then return [] end + + compat_found = false + p.os_list.each do |o| + # check parent pkgs first + if not @parent.nil? then + parent_pkgs = Dir.glob("#{@parent.source_path}/#{p.package_name}_*_*.zip") + parent_pkgs.each do |lp| + lpname = Utils.get_package_name_from_package_file( lp ) + lver = Utils.get_version_from_package_file(lp) + los = Utils.get_os_from_package_file( lp ) + if lpname == p.package_name and o == los and lver == p.version then + compat_pkgs.push [p.package_name,o,lp] + compat_found = true + break + end + end + end + if compat_found then break end + + # check other package already in package server + ver_svr = @pkgsvr_client.get_attr_from_pkg( p.package_name, o, "version") + if not ver_svr.nil? and p.version.eql? ver_svr then + compat_pkgs.push [p.package_name,o,nil] + compat_found = true + break + end + end + + # if there is no compat pkgs for one pkg, then must build + if not compat_found then return [] end + end + + return compat_pkgs + end + + + def build_normal() + @log.info( "Started to build this job...", Log::LV_USER) + + # create builder + if @is_remote_job then + builder = RemoteBuilder.new("JB#{@id}", @remote_server, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd) + @log.info( "JobBuilder##{@id} is created", Log::LV_USER) + @log.info( " - Remote Server : #{@remote_server.ip}:#{@remote_server.port}" ) + if not @server.ftp_addr.nil? then + @log.info( " - FTP Server : #{@server.ftp_addr}" ) + end + else + builder = Builder.create( "JB#{@id}", @pkgsvr_url, nil, + "#{@buildroot_dir}", @server.build_cache_dir ) + if builder.nil? + @log.error( "Creating job builder failed", Log::LV_USER) + return false + end + @log.info( "JobBuilder##{@id} is created", Log::LV_USER) + @log.info( " - Package Server : #{@pkgsvr_url}" ) + @log.info( " - Build Cache Path : #{@server.build_cache_dir}" ) + end + @log.info( " - Log Path : #{@log.path}" ) + + # if sub job, install dependent packages of parent-pkgs and not clean + use_clean = true + local_pkgs = [] + local_pkgs += @external_pkgs + if not @parent.nil? then + use_clean = false + # get local packages to install + deps = @pkginfo.get_build_dependencies(@os) + local_pkgs += get_local_paths_of_chained_dependencies( deps, @parent ) + end + local_pkgs.uniq! + + #compatable os support + compat_ok = true + compat_pkgs = check_compatable_packages + if compat_pkgs.size > 0 and not @is_rev_build_check_job then + # bring package from server for reverse check + compat_pkgs.each do |p| + pkg_name = p[0]; cos = p[1]; local_path = p[2] + + if not local_path.nil? then + ext = File.extname(local_path) + base_package_name= File.basename(local_path, "#{cos}#{ext}") + @log.info( "Copying compatible package:#{local_path}", Log::LV_USER) + @log.info( "Creating package file ... #{base_package_name}#{@os}#{ext}", Log::LV_USER) + FileUtils.cp local_path, "#{@source_path}/#{base_package_name}#{@os}#{ext}" + else + @log.info( "Downloading compatible package:#{pkg_name}(#{cos})", Log::LV_USER) + loc = @pkgsvr_client.download(pkg_name, cos, false) + if loc.nil? or loc.count != 1 then + @log.warn( "Downloading compatible package failed!:#{pkg_name}(#{cos})", Log::LV_USER) + compat_ok = false + break + end + ext = File.extname(loc[0]) + base_package_name= File.basename(loc[0], "#{cos}#{ext}") + @log.info( "Creating package file ... #{base_package_name}#{@os}#{ext}", Log::LV_USER) + FileUtils.mv loc[0], "#{@source_path}/#{base_package_name}#{@os}#{ext}" + end + end + else + compat_ok = false + end + + # if compat check failed + if not compat_ok then + # build + if @is_remote_job then + result = builder.build_job(self, local_pkgs) else - dep_target_os = @os + result = builder.build_job(self, use_clean, local_pkgs, false ) end - ver_svr = @pkgsvr_client.get_attr_from_pkg( dep.package_name, dep_target_os, "version") + if not result then + @log.error( "Building job failed", Log::LV_USER) + write_log_url() + return false + end + end - if ver_svr.nil? - @log.error( "The package \"#{dep.package_name}\" for build-dependency is not found}", Log::LV_USER) + # check reverse dependecy if not sub jobs + + if not @no_reverse then + if not @is_rev_build_check_job and not @is_internal_job and + not ReverseBuildChecker.check( self, true ).empty? then + @log.error( "Reverse-build-check failed!" ) return false end + end + + return true + end + - if not dep.match? ver_svr - @log.error( "Version for build-dependency in not matched : server version => #{ver_svr}", Log::LV_USER) + # wait to be resolved by other jobs + def wait_resolve() + @log.info( "Started to build this job and wait for being resolved...", Log::LV_USER) + + # create builder + if @is_remote_job then + builder = RemoteBuilder.new("JB#{@id}", @remote_server, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd) + @log.info( "JobBuilder##{@id} is created", Log::LV_USER) + @log.info( " - Remote Server : #{@remote_server.ip}:#{@remote_server.port}" ) + if not @server.ftp_addr.nil? then + @log.info( " - FTP Server : #{@server.ftp_addr}" ) + end + else + builder = Builder.create( "JB#{@id}", @pkgsvr_url, nil, + "#{@buildroot_dir}/#{@os}", @server.build_cache_dir ) + if builder.nil? + @log.error( "Creating job builder failed", Log::LV_USER) return false end - end - + @log.info( "JobBuilder##{@id} is created", Log::LV_USER) + @log.info( " - Package Server : #{@pkgsvr_url}" ) + @log.info( " - Build Cache Path : #{@server.build_cache_dir}" ) + end + @log.info( " - Log Path : #{@log.path}" ) + + # build + if @is_remote_job then + result = builder.build_job(self, []) + else + result = builder.build_job(self, true, [], false ) + end + if not result then + @log.error( "Building job failed", Log::LV_USER) + write_log_url() + return false + end + + # check reverse dependecy + @rev_fail_projects = ReverseBuildChecker.check(self, false) + if @rev_fail_projects.empty? then + # if no problem?, it OK + return true + end + + # pending + @status = "PENDING" + @log.info( "Entered the PENDING state ...", Log::LV_USER) + old_msg = "" + while @status == "PENDING" + new_msg = @rev_fail_projects.map {|p| "#{p[0].name}(#{p[1]})"}.join(", ") + if old_msg != new_msg then + @log.error( " * Waiting for building next projects: #{new_msg}", Log::LV_USER) + old_msg = new_msg + end + sleep 1 + end + return true end - # build clean - def build() - if @resolve then - @log.info( "Resolving job...", Log::LV_USER) + # resolve other pending job + def resolve() + + # wait for other build-dependent projects are resolved + old_msg = "" + wait_prjs = @pending_ancestor.rev_fail_projects.select {|p| is_build_dependent_project(p[0], p[1])} + @log.info("Checking build dependency before RESOLVE", Log::LV_USER) + while not wait_prjs.empty? + @status = "PENDING" + new_msg = wait_prjs.map {|p| "#{p[0].name}(#{p[1]})"}.join(", ") + if new_msg != old_msg then + @log.info(" * Waiting for building next projects: #{new_msg}", Log::LV_USER) + old_msg = new_msg + end + sleep 1 + wait_prjs = @pending_ancestor.rev_fail_projects.select {|p| is_build_dependent_project(p[0], p[1])} + end + + # return back to "WORKING" + @status = "WORKING" + + @log.info( "Started to build this job and resolve other pending job...", Log::LV_USER) + + # create builder + if @is_remote_job then + builder = RemoteBuilder.new("JB#{@id}", @remote_server, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd) + @log.info( "JobBuilder##{@id} is created", Log::LV_USER) + @log.info( " - Remote Server : #{@remote_server.ip}:#{@remote_server.port}" ) + if not @server.ftp_addr.nil? then + @log.info( " - FTP Server : #{@server.ftp_addr}" ) + end else - @log.info( "Building job...", Log::LV_USER) - end + builder = Builder.create( "JB#{@id}", @pkgsvr_url, nil, + "#{@buildroot_dir}/#{@os}", @server.build_cache_dir ) + if builder.nil? + @log.error( "Creating job builder failed", Log::LV_USER) + return false + end + @log.info( "JobBuilder##{@id} is created", Log::LV_USER) + @log.info( " - Package Server : #{@pkgsvr_url}" ) + @log.info( " - Build Cache Path : #{@server.build_cache_dir}" ) + end + @log.info( " - Log Path : #{@log.path}" ) + + # get local packages to overwite + # they must be composed of packages of pending jobs and its success list + local_pkgs=[] + local_pkgs += @external_pkgs + src_path = @pending_ancestor.source_path + ver = @pending_ancestor.pkginfo.get_version() + @pending_ancestor.pkginfo.get_target_packages(@os).each do |pkg| + local_pkgs.push "#{src_path}/#{pkg.package_name}_#{ver}_#{@os}.zip" + end + @pending_ancestor.rev_success_jobs.each do |job| + src_path = job.source_path + ver = job.pkginfo.get_version() + job.pkginfo.get_target_packages(@os).each do |pkg| + local_pkgs.push "#{src_path}/#{pkg.package_name}_#{ver}_#{@os}.zip" + end + end - # create builder - builder = Builder.create( "JB#{@id}", @pkgserver_url,@log.path ) - if builder.nil? - @log.error( "Creating job builder failed", Log::LV_USER) + # build + if @is_remote_job then + result = builder.build_job(self, local_pkgs) + else + result = builder.build_job(self, true, local_pkgs, false ) + end + if not result then + @log.error( "Building job failed", Log::LV_USER) + write_log_url() return false end - @log.info( "JobBuilder##{@id} is created", Log::LV_USER) - - # set log output - builder.log.close - builder.log = @log - - #make pending_pkg_dir_list - pending_pkg_dir_list = [] - ignore_rev_dep_build_list = [] - @pkginfo.packages.each do |i| - @server.pending_jobs.each do |pj| - if pj.rev_fail_list.include? i.package_name then - pending_pkg_dir_list.push pj.source_path - pending_pkg_dir_list += pj.rev_success_list.map {|pjs| pjs.source_path} - ignore_rev_dep_build_list = pj.rev_fail_list - break - end - end - if not pending_pkg_dir_list.empty? then break end - end - dependency_package_exist = (not pending_pkg_dir_list.empty?) - - # build - if @resolve then - @rev_fail_list = builder.build_resolve(@source_path, @os, [], []) - - # clean build failed - if @rev_fail_list.nil? then - @log.error( "Resolve building job failed", Log::LV_USER) - return false - end - - # pending - @status = "PENDING" - - # rev build successed - if @rev_fail_list.empty? then - @rev_success_list.each do |s| - s.status = "" - end - @status = "" - end - - while @status == "PENDING" - sleep 1 - end - return true - else - if not builder.build(@source_path, @os, true, true, pending_pkg_dir_list, ignore_rev_dep_build_list ) - @log.error( "Building job failed", Log::LV_USER) - return false - end - - if dependency_package_exist then - @server.pending_jobs.each do |j| - if j.source_path == pending_pkg_dir_list[0] then - j.rev_fail_list -= @pkginfo.packages.map{|p| p.package_name} - j.rev_success_list.push self - if j.rev_fail_list.empty? then - j.rev_success_list.each do |s| - s.status = "" - end - j.status = "" - else - @status = "PENDING" - while @status == "PENDING" - sleep 1 - end - end - break - end - end - end - end - - # remove builder - Builder.remove( "builder_#{@id}" ) - + + # check reverse dependecy and update parent rev_fail_project list + new_fail_projects = ReverseBuildChecker.check(self, false) + new_fail_projects.each do |p| + @pending_ancestor.add_rev_fail_project(p[0], p[1]) + end + + # update the status of pending job + @status = "PENDING" + @pending_ancestor.remove_rev_fail_project(@project, @os) + @pending_ancestor.rev_success_jobs.push self + if @pending_ancestor.rev_fail_projects.empty? then + @pending_ancestor.status = "RESOLVED" + @pending_ancestor.rev_success_jobs.each do |job| + job.status = "RESOLVED" + end + else + @log.info( "Entered the PENDING state ...", Log::LV_USER) + old_msg = "" + while @status == "PENDING" + new_msg = @pending_ancestor.rev_fail_projects.map {|p| "#{p[0].name}(#{p[1]})"}.join(", ") + + if new_msg != old_msg then + @log.info(" * Waiting for building next projects: #{new_msg}", Log::LV_USER) + old_msg = new_msg + end + + sleep 1 + end + end + return true end def upload() @log.info( "Uploading ...", Log::LV_USER) - + # get package path list binpkg_path_list = Dir.glob("#{@source_path}/*_*_#{@os}.zip") - srcpkg_path_list = Dir.glob("#{@source_path}/*.tar.gz") # upload - u_client = Client.new( @server.pkgserver_url, nil, @log ) - u_client.update - snapshot = u_client.upload( @server.pkgserver_addr, - @server.pkgserver_id, binpkg_path_list, srcpkg_path_list, true) + u_client = Client.new( @pkgsvr_url, nil, @log ) + snapshot = u_client.upload( @pkgsvr_ip, @pkgsvr_port, binpkg_path_list, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd) if snapshot.nil? then @log.info( "Upload failed...", Log::LV_USER) return false end - + # update local @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER) @pkgsvr_client.update - @server.local_pkgsvr.sync( @server.local_pkgsvr.get_default_dist_name(), false ) @log.info("Snapshot: #{snapshot}", Log::LV_USER) - + return true end - # remote main module - def remote_thread_main(server) - @log.info( "Job #{@id} is requested to be built on remote server ", Log::LV_USER) - - @status = "REMOTE_BUILDING" + def copy_result_files(dst_path) + @log.info( "Copying result files to #{dst_path}", Log::LV_USER) - # open - client = BuildCommClient.create( server.remote_ip, server.port ) - if client.nil? then - @status = "ERROR" - return - end - - # send & receive - if client.send("BUILD,GIT,#{@git_repos},#{@git_commit},#{@os},,NO") then - result = client.read_lines do |l| - if l.include? "Job is stopped by ERROR" then - @status = "ERROR" - end - # ddd list - @log.output( l.strip, Log::LV_USER) + # get package path list + binpkg_path_list = Dir.glob("#{@source_path}/*_*_#{@os}.zip") + + binpkg_path_list.each do |file| + @log.info( " * #{file}", Log::LV_USER) + FileUtils.cp(file,"#{dst_path}/") + end + + return true + end + + + # copy binary package files and log file to transport dir + def copy_result_files_to_master() + outgoing_dir = "#{@server.transport_path}/#{@dock_num}" + + @log.info( "Copying log to #{outgoing_dir}", Log::LV_USER) + file = "#{@source_path}/../log" + FileUtils.copy_file(file, "#{outgoing_dir}/remote_log") + + # copy result files, if not reverse build + if not @is_rev_build_check_job then + return copy_result_files( outgoing_dir ) + else + return true + end + end + + + protected + def get_local_path_of_dependency( dep, parent ) + dep_target_os = get_os_of_dependency(dep) + + # search my parent job and its parent job + binpkgs = Dir.glob("#{parent.source_path}/#{dep.package_name}_*_#{dep_target_os}.zip") + if binpkgs.count == 0 and not parent.get_parent_job().nil? then + binpkgs = Dir.glob("#{parent.get_parent_job().source_path}/#{dep.package_name}_*_#{dep_target_os}.zip") + end + + if binpkgs.count > 0 then + pkg = binpkgs[0] + version = Utils.get_version_from_package_file(pkg) + if dep.match? version then + return pkg + else + return nil end - if not result then @status = "ERROR" end + else + return nil end + end - # close socket - client.terminate - # INFO. don't change this string - if @status != "ERROR" then - @log.info( "Job is just finished", Log::LV_USER) - @status = "FINISHED" + protected + def get_local_paths_of_chained_dependencies( deps, parent ) + pkg_paths = [] + + # get packages names that is related my build dependency + chained_deps = get_local_chained_dependencies( deps, parent ) + + # get all local path of dependencies + chained_deps.each do |dep| + new_path = get_local_path_of_dependency(dep, parent) + if not new_path.nil? then + pkg_paths.push new_path + end end - return + # remove duplicates + pkg_paths.uniq! + + return pkg_paths + end + + + protected + def get_local_chained_dependencies( deps, parent ) + + chained_deps = [] + chained_deps += deps + + # if parent is multi build job, gether all install dependency of dependency. + if parent.type == "MULTIBUILD" then + begin + old_deps_count = chained_deps.count + new_deps = [] + chained_deps.each do |dep| + dep_target_os = get_os_of_dependency(dep) + + parent.get_sub_jobs().each do |j| + new_deps += j.pkginfo.get_install_dependencies(dep_target_os, dep.package_name) + end + end + chained_deps += new_deps + chained_deps.uniq! {|d| d.package_name } + end while chained_deps.count != old_deps_count + end + + # check parent of parent + if not parent.get_parent_job().nil? then + chained_deps = get_local_chained_dependencies(chained_deps, parent.get_parent_job()) + end + + return chained_deps + end + + + protected + def remote_package_of_dependency_exist?(dep) + dep_target_os = get_os_of_dependency(dep) + + # search + ver_svr = @pkgsvr_client.get_attr_from_pkg( dep.package_name, dep_target_os, "version") + if ver_svr.nil? then return false end + if not dep.match? ver_svr then return false end + + return true + end + + + # write web url for log + protected + def write_log_url() + url,remote_url = get_log_url() + if not url.empty? then + @log.info( " ** Log1: #{url}", Log::LV_USER) + end + if not remote_url.empty? then + @log.info( " ** Log2: #{remote_url}", Log::LV_USER) + end + end + + + # get target os of dependency + protected + def get_os_of_dependency(dep) + # use the target os if not specified + if dep.target_os_list.count != 0 then + dep_target_os = dep.target_os_list[0] + else + dep_target_os = @os + end end end diff --git a/src/build_server/BuildServer.rb b/src/build_server/BuildServer.rb index 7862f98..7328abe 100644 --- a/src/build_server/BuildServer.rb +++ b/src/build_server/BuildServer.rb @@ -1,5 +1,5 @@ =begin - + BuildServer.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -26,154 +26,276 @@ Contributors: - S-Core Co., Ltd =end +require 'rubygems' require 'fileutils' +require 'dbi' +require 'thread' $LOAD_PATH.unshift File.dirname(__FILE__) -$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server" require "SocketJobRequestListener.rb" -require "RemoteBuildJob.rb" -require "LocalBuildJob.rb" -require "packageServer.rb" +require "JobManager.rb" +require "JobClean.rb" +require "RemoteBuildServer.rb" +require "PackageSync.rb" +require "ProjectManager.rb" +require "DistributionManager.rb" class BuildServer - attr_accessor :id, :path, :pkgserver_url, :pkgserver_addr, :pkgserver_id, :remote_ip, :port, :status, :friend_servers, :host_os, :log - attr_accessor :max_working_jobs, :working_jobs, :waiting_jobs, :remote_jobs, :pending_jobs + attr_accessor :id, :path, :status, :host_os, :log + attr_accessor :remote_servers attr_accessor :git_server_url, :git_bin_path - attr_accessor :job_log_url - attr_accessor :job_index attr_accessor :allowed_git_branch - attr_accessor :pkgsvr_cache_path, :local_pkgsvr - + attr_accessor :jobmgr + attr_accessor :test_time + attr_accessor :password + attr_accessor :finish + attr_accessor :build_cache_dir + attr_accessor :ftp_addr + attr_accessor :ftp_port + attr_accessor :ftp_username + attr_accessor :ftp_passwd + attr_accessor :cleaner + attr_accessor :prjmgr, :distmgr + attr_accessor :transport_path + attr_accessor :cancel_lock + attr_accessor :upgrade + attr_accessor :db + attr_accessor :db_dsn, :db_user, :db_passwd, :db_version CONFIG_ROOT = "#{Utils::HOME}/.build_tools/build_server" HOST_OS = Utils::HOST_OS # initialize - def initialize (id, path, pkgserver_url, pkgserver_addr, pkgserver_id) + def initialize (id, path, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd) @id = id @path = path - @pkgserver_url = pkgserver_url - @pkgserver_addr = pkgserver_addr - @pkgserver_id = pkgserver_id - @friend_servers = [] - @waiting_jobs = [] - @working_jobs = [] - @pending_jobs = [] - @remote_jobs = [] - @max_working_jobs=2 + @remote_servers = [] @req_listener = [] @finish = false - # for friend server - @remote_ip = nil - # port number - @port = 2222 # status @status = "RUNNING" # host_os @host_os = HOST_OS # log - @log = nil + @log =nil @git_server_url = "gerrithost" @git_bin_path = "/usr/bin/git" - @job_index = 0 - @job_log_url = "" @allowed_git_branch = "" # local package server @pkgsvr_cache_path = nil - @local_pkgsvr = nil + # Job Manager + @jobmgr = JobManager.new(self) + @test_time=0 #test time in mili-seconds + @password="0000" + @ftp_addr = ftpsvr_addr + @ftp_port = ftpsvr_port + @ftp_username = ftpsvr_username + @ftp_passwd = ftpsvr_passwd + @cleaner=nil + @prjmgr = ProjectManager.new(self) + @distmgr = DistributionManager.new(self) + # + @transport_path = "#{@path}/transport" + @cancel_lock = Mutex.new + + @upgrade = false + + #DB settring + @db = nil + @db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{@id}/server.db" + @db_user = nil + @db_passwd = nil + @db_version = 1 + @sqlite3_db_mutex = Mutex.new + + #DB upgrade SQL command + @db_migrate = [] + #@db_migrate[0]= ["CREATE TABLE test(value INTEGER)", "INSERT INTO test (value) VALUES('3')"] + end + + def send_mail + result = nil + get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'send_mail'")[0] + end + return (result.nil?) ? "NO" : result + end + + def send_mail=(mail) + get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{mail}' WHERE property = 'send_mail'" + end + end + + def keep_time + result = nil + get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'keep_time'")[0] + end + return (result.nil?) ? 86400 : result.to_i + end + + def keep_time=(second) + get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{second}' WHERE property = 'keep_time'" + end end + def pkg_sync_period + result = nil + get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'pkg_sync_period'")[0] + end + return (result.nil?) ? 600 : result.to_i + end + def pkg_sync_period=(second) + get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{second}' WHERE property = 'pkg_sync_period'" + end + end + + def changelog_check + result = nil + get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'changelog_check'")[0] + end + return (result.nil?) ? false : result =~ /true/i + end + + def changelog_check=(check) + t = check =~ /true/i + get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{t.to_s}' WHERE property = 'changelog_check'" + end + end + + def job_log_url + result = nil + get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'job_log_url'")[0] + end + return (result.nil?) ? "" : result + end + + def job_log_url=(url) + get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{url}' WHERE property = 'job_log_url'" + end + end + + def port + result = nil + get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'port'")[0] + end + return (result.nil?) ? "" : result + end + + def port=(svr_port) + get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{svr_port}' WHERE property = 'port'" + end + end + + def db_inc + return (@db_dsn =~ /^Mysql/i) ? "AUTO_INCREMENT" : "AUTOINCREMENT" + end + + def db_post_fix + return (@db_dsn =~ /^Mysql/i) ? "ENGINE = INNODB DEFAULT CHARSET = UTF8" : "" + end + + def db_now + return (@db_dsn =~ /^Mysql/i) ? "NOW()" : "datetime('now')" + end # start server daemon def start - # start logger - @log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{@id}/log" ) - - # set local package server for cache - @log.info "Setting local package server..." - pkgsvr_id = @id - pkgsvr_dist = @pkgserver_url.split("/")[-1] - @local_pkgsvr = PackageServer.new( pkgsvr_id ) - if @local_pkgsvr.location.empty? then - FileUtils.mkdir_p @pkgsvr_cache_path - @local_pkgsvr.create(pkgsvr_id, pkgsvr_dist, @pkgserver_url, @pkgsvr_cache_path ) - else - # check path is changed, recreate it - if @local_pkgsvr.location != "#{@pkgsvr_cache_path}/#{pkgsvr_id}" then - # remove - @local_pkgsvr.remove_server( pkgsvr_id ) - # create - FileUtils.mkdir_p @pkgsvr_cache_path - @local_pkgsvr.create(pkgsvr_id, pkgsvr_dist, @pkgserver_url, @pkgsvr_cache_path ) - end + # set build cache dir + @build_cache_dir="#{BuildServer::CONFIG_ROOT}/#{@id}/build_cache" + if not File.exist? @build_cache_dir then + FileUtils.mkdir_p @build_cache_dir end + # init transport path + if not File.exist? @transport_path then FileUtils.mkdir_p @transport_path end + + # init project mgr + @log.info "Setting Project Manager..." + @prjmgr.load() + + # init job mgr + @log.info "Intializing Job Manager..." + @jobmgr.init() + # set job request listener @log.info "Setting listener..." listener2 = SocketJobRequestListener.new(self) listener2.start @req_listener.push listener2 - - # main loop - @log.info "Entering main loop..." - while( not @finish ) - # handle jobs - handle() - sleep 1 - end - end + # set job cleaner + @log.info "Setting Job Cleaner..." + @cleaner = JobCleaner.new(self) + @cleaner.start - # stop sever daemon - def stop - @finish = true - end + # set package server synchrontizer + @log.info "Setting Package Server Synchronizer..." + @pkg_sync = PackageServerSynchronizer.new(self) + @pkg_sync.start + # main loop + @log.info "Entering main loop..." + begin + if @test_time > 0 then start_time = Time.now end + while( not @finish ) + + # update friend server status + @remote_servers = get_remote_servers() + @remote_servers.each do |server| + # update state + get_db_connection() do |db| + server.update_state(db) + end + end - # add a normal job - def add_job ( new_job ) - @log.info "Added new job \"#{new_job.id}\"" - - Thread.new { - # pre-verifiy - if not new_job.pre_verify or new_job.status == "ERROR" then - new_job.status = "ERROR" - @log.info "Adding the job \"#{new_job.id}\" is canceled" - new_job.terminate() - Thread.current.exit - end + # handle jobs + @jobmgr.handle() - # check availabiltiy - if not check_job_availability( new_job ) then - new_job.log.error( "No servers that are able to build your packages.", Log::LV_USER) - new_job.status = "ERROR" - @log.info "Adding the job \"#{new_job.id}\" is canceled" - new_job.terminate() - Thread.current.exit + # sleep + if @test_time > 0 then + curr_time = Time.now + if (curr_time - start_time).to_i > @test_time then + puts "Test time is elapsed!" + break + end + else + sleep 1 + end end + rescue => e + @log.error( e.message, Log::LV_USER) + @log.error e.backtrace.inspect + end - @waiting_jobs.push( new_job ) - new_job.status = "WAITING" - @log.info "Checking the job \"#{new_job.id}\" was finished!" - } - end - - - # get job list - def get_job_list() - list = [] - list = list + @working_jobs + @remote_jobs + @waiting_jobs + if(@upgrade) + exit(99) + end + # TODO: something should be done for server down - return list end - # query job status - def get_job_status( job ) - return job.status + # stop sever daemon + def stop + @finish = true end # check the job can be built on this server def can_build?(job) + # check max allowed jobs + if @jobmgr.max_working_jobs <= 0 then + return false + end # check me if job.can_be_built_on? @host_os then @@ -184,294 +306,176 @@ class BuildServer end - def get_new_job_id - # get new id - new_id = @job_index - - # save it - server_dir = "#{BuildServer::CONFIG_ROOT}/#{@id}" - f = File.open( "#{server_dir}/latest_job", "w" ) - f.puts "#{new_id}" - f.close - - # increae job idex - @job_index = @job_index + 1 - - return new_id + def get_remote_servers() + get_db_connection() do |db| + return RemoteBuildServer.load_all(db) + end end # add new remote friend server - def add_friend_server( ip, port ) - - # if already exit, return false - for svr in @friend_servers - if svr.remote_ip.eql? ip and svr.port == port then - return false - end - end - - # create new one, and add it into list - new_server = BuildServer.new( "#{ip}_#{port}", nil, nil, nil, nil ) - new_server.remote_ip = ip - new_server.port = port - new_server.status = "UNDEFINED" - @friend_servers.push new_server + def add_remote_server( ip, port ) + + get_db_connection() do |db| + rs = RemoteBuildServer.load(ip, port, db) + if not rs.nil? then return false end + RemoteBuildServer.new(ip, port, "").save(db) + end return true end - # query remote server info & update server state - def update_state + # remove remote friend server + def remove_remote_server( ip, port ) + get_db_connection() do |db| + rs = RemoteBuildServer.load(ip, port, db) + if rs.nil? then return false end + rs.unload(db) + end - # only friend server - if not @path.nil? then return end + return true + end - # send - @status = "DISCONNECTED" - client = BuildCommClient.create( @remote_ip, @port ) - if client.nil? then return end - if client.send("QUERY,SYSTEM") then - result = client.read_lines do |l| - tok = l.split(",").map { |x| x.strip } - @host_os = tok[0] - @max_working_jobs = tok[1].to_i - @status = "RUNNING" - end - if not result then @status = "DISCONNECTED" end - end - client.terminate - if @status == "DISCONNECTED" then return end - - # send - @working_jobs = [] - @waiting_jobs = [] - client = BuildCommClient.create( @remote_ip, @port ) - if client.nil? then return end - if client.send("QUERY,JOB") then - result = client.read_lines do |l| - tok = l.split(",").map { |x| x.strip } - - job_status = tok[0] - job_id = tok[1] - new_job = RemoteBuildJob.new(job_id) - case job_status - when "WAITING" - @waiting_jobs.push new_job - when "WORKING" - @working_jobs.push new_job - else - #puts "Uncontrolled status" - end + + def get_sync_package_servers() + result = [] + get_db_connection() do |db| + rows = db.select_all("SELECT sync_pkg_servers.pkgsvr_url, distributions.name FROM sync_pkg_servers,distributions WHERE sync_pkg_servers.distribution_id = distributions.id") + rows.each do |row| + result.push [row['pkgsvr_url'], row['name']] end - if not result then @status = "DISCONNECTED" end - else - @status = "DISCONNECTED" end - client.terminate - end + return result + end - private - def handle() - # update friend server status - for server in @friend_servers - # update state - server.update_state + # add new remote pkg server + def add_sync_package_server( url, dist ) + get_db_connection() do |db| + row = db.select_one("SELECT distributions.id FROM sync_pkg_servers,distributions WHERE sync_pkg_servers.pkgsvr_url='#{url}' and distributions.name='#{dist}' and sync_pkg_servers.distribution_id = distributions.id") + if not row.nil? then return false end + row = db.select_one("SELECT id FROM distributions WHERE name='#{dist}'") + dist_id = row['id']; + db.do "INSERT INTO sync_pkg_servers (pkgsvr_url,period,distribution_id) VALUES('#{url}','#{@pkg_sync_period}',#{dist_id})" end - # Move working -> finished - #) Move working -> pending - for job in @working_jobs - if job.status == "ERROR" - @log.info "Job \"#{job.id}\" is stopped by ERROR" - @working_jobs.delete job - elsif job.status == "FINISHED" - @working_jobs.delete job - elsif job.status == "PENDING" - @working_jobs.delete job - @pending_jobs.push job - end - end + return true + end - # Move pending -> finished - for job in @pending_jobs - if job.status == "ERROR" - @log.info "Job \"#{job.id}\" is stopped by ERROR" - @pending_jobs.delete job - elsif job.status == "FINISHED" - @pending_jobs.delete job - end - end - # Move remote -> finished - for job in @remote_jobs - if job.status == "ERROR" - @log.info "Job \"#{job.id}\" is stopped by ERROR" - @remote_jobs.delete job - elsif job.status == "FINISHED" - @remote_jobs.delete job - end + # remove remote pkg server + def remove_sync_package_server( url, dist ) + get_db_connection() do |db| + row = db.select_one("SELECT distributions.id FROM sync_pkg_servers,distributions WHERE sync_pkg_servers.pkgsvr_url='#{url}' and distributions.name='#{dist}' and sync_pkg_servers.distribution_id = distributions.id") + if row.nil? then return false end + dist_id = row['id']; + db.do("DELETE FROM sync_pkg_servers WHERE pkgsvr_url='#{url}' and distribution_id=#{dist_id}") end - # MOVE waiting -> finished - for job in @waiting_jobs - if job.status == "ERROR" then - @waiting_jobs.delete( job ) - @log.info "Job \"#{job.id}\" is removed by internal error" + return true + end + + + def supported_os_list + result = [] + get_db_connection() do |db| + rows = db.select_all("SELECT * FROM supported_os") + rows.each do |row| + result.push row['name'] end end - # MOVE waiting -> working - if @waiting_jobs.count > 0 then - - # get available job - job = get_available_job - - # available job not exist?, continue - if ( job.nil? ) then return end + return result + end - # oherwise, check remote server - rserver = get_available_server( job ) - # request for build - if rserver != nil and rserver == self then + # add new target OS. + # If already exist, return false , otherwise true + def add_supported_os( os_name ) + os_category = Utils.get_os_category( os_name ) + if os_category.nil? then return false end - # change - @waiting_jobs.delete job - @working_jobs.push job + get_db_connection() do |db| + row = db.select_one("SELECT * FROM supported_os WHERE name='#{os_name}'") + if not row.nil? then return false end + db.do "INSERT INTO supported_os(os_category_id, name) SELECT os_category.id, '#{os_name}' FROM os_category WHERE os_category.name='#{os_category}'" + end - # start build - job.execute - @log.info "Moved the job \"#{job.id}\" to working job list" + return true + + end - elsif rserver != nil then - if job.execute_remote( rserver ) then - # status change & job control - job.status = "REMOTE_WAITING" - @waiting_jobs.delete( job ) - @remote_jobs.push( job ) - @log.info "Moved the job \"#{job.id}\" to remote job list" - else - @log.info "Moving the job \"#{job.id}\" to remote failed" - end - else - #puts "No available server" - end + # remove target OS. + def remove_supported_os( os_name ) + get_db_connection() do |db| + row = db.select_one("SELECT * FROM supported_os WHERE name='#{os_name}'") + if row.nil? then return false end + db.do("DELETE FROM supported_os WHERE name='#{os_name}'") end - #check the connection if the waiting job is not asynchronous job - for job in @waiting_jobs - if not job.is_asynchronous_job? and not job.is_connected? then - @waiting_jobs.delete( job ) - @log.info "Job \"#{job.id}\" is disconneted by user. Removed!" - end - end - for job in @remote_jobs - if not job.is_asynchronous_job? and not job.is_connected? then - @remote_jobs.delete( job ) - @log.info "Job \"#{job.id}\" is disconneted by user. Removed!" - end - end - + return true end - # select the job whith no build-dependency problem - def get_available_job - - # gather all working jobs - all_working_jobs = [] + @working_jobs - all_working_jobs = all_working_jobs + @remote_jobs - - # for waiting jobs - for job in @waiting_jobs - blocked_by = [] - is_changed = false - - # should not have same packages with workings - # should not depend on workings - # should not be depended by workings - for wjob in all_working_jobs - if job.has_same_packages?( wjob ) or - job.does_depend_on?( wjob ) or - job.does_depended_by?( wjob ) then - - blocked_by.push wjob - # if there are some changes, check it - if not job.blocked_by.include? wjob then is_changed = true end - end - end - - # if available , then FIFO - if blocked_by.empty? then - job.blocked_by = [] - return job - else - # check count - if blocked_by.count != job.blocked_by.count then is_changed = true end - - # if somthing changed, print it and save it - if is_changed then - job.log.info( "Waiting for finishing following jobs:", Log::LV_USER) - for bjob in blocked_by - job.log.info( " * #{wjob.id} #{wjob.pkginfo.packages[0].source}", Log::LV_USER) - end - job.blocked_by = blocked_by - end - end + def self.get_supported_os_id(db, os_name) + row = db.select_one("SELECT * FROM supported_os WHERE name='#{os_name}'") + if not row.nil? then + return row['id'] + else + return "NULL" end - - return nil end - # get remote server + # get remote server def get_available_server ( job ) candidates = [] - - # check local - if @working_jobs.count < @max_working_jobs and can_build?(job) then + + # calculate empty rooms + # if sub job, his parent should be excluded + local_empty_rooms = @jobmgr.get_number_of_empty_room + + if local_empty_rooms > 0 and can_build?(job) then candidates.push self end - # if Local build job, just check local - if job.instance_of? LocalBuildJob then return candidates[0] end - - # get availables - for server in @friend_servers - # select only "RUNNING" & possible one - if ( server.status == "RUNNING" and server.can_build?( job ) and - server.waiting_jobs.count == 0 and - server.working_jobs.count < server.max_working_jobs ) - candidates.push server + # get availables server + # but, job must not be "REGISTER" and "MULTIBUILD" job + if job.type != "REGISTER" and job.type != "MULTIBUILD" then + @remote_servers.each do |server| + if ( server.status == "RUNNING" and server.can_build?( job ) and + not server.has_waiting_jobs and + server.get_file_transfer_cnt() == 0 and + server.get_number_of_empty_room > 0 ) + candidates.push server + end end end best_server = candidates[0] if best_server.nil? or candidates.count == 1 then return best_server end - # get best + # get best # it is better if working jobs count is less - max_empty_room = best_server.max_working_jobs - best_server.working_jobs.count - for server in candidates - # check whether idle, use it - if server.working_jobs.count == 0 then return server end + max_empty_room = best_server.get_number_of_empty_room + candidates.each do |server| + # check whether idle, use it + if not server.has_working_jobs then return server end # skip if server == best_server then next end - + # compare remain rooms - empty_room = server.max_working_jobs - server.working_jobs.count + empty_room = server.get_number_of_empty_room if empty_room > max_empty_room then - max_empty_room = empty_root + max_empty_room = empty_room best_server = server end end - + return best_server end @@ -483,8 +487,8 @@ class BuildServer if can_build? job then return true end #if not found, check friends - for server in @friend_servers - if server.status == "RUNNING" and + @remote_servers.each do |server| + if server.status == "RUNNING" and job.can_be_built_on? server.host_os then return true end @@ -492,5 +496,271 @@ class BuildServer return false end + + + # return available working slot + def get_number_of_empty_room + return @jobmgr.get_number_of_empty_room + end + + + # check there are working jobs + def has_working_jobs + return @jobmgr.has_working_jobs + end + + + # check there are waiting jobs + def has_waiting_jobs + return @jobmgr.has_waiting_jobs + end + + def get_dbversion + db_version = nil + begin + db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd) + db_version = db.select_one("SELECT (value) FROM server_configs WHERE property = 'db_version'")[0].to_i + rescue DBI::DatabaseError => e + #puts e.errstr + ensure + db.disconnect if db + end + return db_version + end + + def db_upgrade + result = true + create = false + begin + db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd) + db_version = db.select_one("SELECT (value) FROM server_configs WHERE property = 'db_version'")[0].to_i + if db_version.nil? then + create = true + else + list = @db_migrate[db_version..@db_version] + if not list.nil? then + list.each do |sql_list| + sql_list.each do |sql| + db.do sql + end + end + end + end + rescue DBI::DatabaseError => e + puts e.errstr + result = false + ensure + db.disconnect if db + end + if create then create_db end + return result + end + + def gen_db() + case @db_dsn + when /^SQLite3:/ then puts "SQLite3 DB#{@db_dsn.split(':')[1]} generating" + when /^Mysql:/ then + name = nil + host = nil + port = nil + socket = nil + flag = nil + dsn = @db_dsn.split(':') + if dsn[2].nil? then + dsn[1].split(';').each do |attr| + case attr.split('=')[0].strip + when /database/i then + name = attr.split('=')[1].strip + when /host/i then + host = attr.split('=')[1].strip + when /port/i then + port = attr.split('=')[1].strip + when /socket/i then + socket = attr.split('=')[1].strip + when /flag/i then + flag = attr.split('=')[1].strip + else + etc = attr.split('=')[1].strip + end + end + else + name = dsn[1].strip + host = dsn[2].strip + end + + File.open("create_db.txt","w") do |f| + f.puts "GRANT ALL ON #{name}.* TO '#{@db_user}'@'%' IDENTIFIED BY '#{@db_passwd}';" + f.puts "CREATE DATABASE #{name};" + end + + if host.eql? "localhost" or host.eql? "127.0.0.1" then + socket_str = "" + socket_str = "--socket=#{socket}" if not socket.nil? + puts "Mysql DB #{name} generating" + system("mysql -h #{host} #{socket_str} -u #{@db_user} --password=#{@db_passwd} < create_db.txt") + else + port_str = "" + port_str = "-P #{port}" if not port.nil? + puts "Mysql DB #{name} generating" + system("mysql -h #{host} #{port_str} -u #{@db_user} --password=#{@db_passwd} < create_db.txt") + end + else puts "not support DB #{@db_dsn}" + end + end + + def create_db() + gen_db() + result = get_db_connection() do |db| + inc = db_inc + post_fix = db_post_fix + now = db_now + + # remove table + db.tables.each do |table| + db.do "DROP TABLE #{table}" + end + + # create table + db.do "CREATE TABLE server_configs ( id INTEGER PRIMARY KEY #{inc}, property VARCHAR(64) NOT NULL, value VARCHAR(256) )#{post_fix}" + db.do "INSERT INTO server_configs (property,value) VALUES ('id','#{@id}')" + db.do "INSERT INTO server_configs (property,value) VALUES ('path','#{@path}')" + db.do "INSERT INTO server_configs (property,value) VALUES ('db_version','#{@db_version}')" + db.do "INSERT INTO server_configs (property,value) VALUES ('port','2222')" + db.do "INSERT INTO server_configs (property,value) VALUES ('max_working_jobs','2')" + db.do "INSERT INTO server_configs (property,value) VALUES ('send_mail','NO')" + db.do "INSERT INTO server_configs (property,value) VALUES ('keep_time','86400')" + db.do "INSERT INTO server_configs (property,value) VALUES ('pkg_sync_period','600')" + db.do "INSERT INTO server_configs (property,value) VALUES ('changelog_check','false')" + db.do "INSERT INTO server_configs (property,value) VALUES ('job_log_url','')" + db.do "CREATE TABLE os_category ( id INTEGER PRIMARY KEY #{inc}, name VARCHAR(32) NOT NULL UNIQUE ) #{post_fix}" + db.do "INSERT INTO os_category (name) VALUES ( 'linux' )" + db.do "INSERT INTO os_category (name) VALUES ( 'windows' )" + db.do "INSERT INTO os_category (name) VALUES ( 'macos' )" + + PackageDistribution.create_table(db, inc, post_fix) + + # sync package server + db.do "CREATE TABLE sync_pkg_servers ( + id INTEGER PRIMARY KEY #{inc}, + distribution_id INTEGER NOT NULL, + pkgsvr_url VARCHAR(256), + period INTEGER, + description VARCHAR(255), + CONSTRAINT fk_sync_pkg_servers_distributions1 FOREIGN KEY ( distribution_id ) REFERENCES distributions ( id ) ) #{post_fix}" + + db.do "CREATE TABLE supported_os ( + id INTEGER PRIMARY KEY #{inc}, + os_category_id INTEGER NOT NULL, + name VARCHAR(32) NOT NULL UNIQUE, + CONSTRAINT fk_supported_os_os_category1 FOREIGN KEY ( os_category_id ) REFERENCES os_category ( id ) ) #{post_fix}" + + RemoteBuildServer.create_table(db, inc, post_fix) + + # USERS/GROUPS + # users + db.do "CREATE TABLE users ( id INTEGER PRIMARY KEY #{inc}, name VARCHAR(32) NOT NULL UNIQUE, email VARCHAR(256), password_hash VARCHAR(256), password_salt VARCHAR(256) ) #{post_fix}" + # groups + db.do "CREATE TABLE groups ( id INTEGER PRIMARY KEY #{inc}, name VARCHAR(32) NOT NULL UNIQUE, admin VARCHAR(32) NOT NULL DEFAULT 'FALSE', description VARCHAR(256) )#{post_fix}" + # user groups (users -- groups) + db.do "CREATE TABLE user_groups ( user_id INTEGER NOT NULL, group_id INTEGER NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', PRIMARY KEY ( user_id, group_id ), + CONSTRAINT fk_users_has_groups_users1 FOREIGN KEY ( user_id ) REFERENCES users ( id ), + CONSTRAINT fk_users_has_groups_groups1 FOREIGN KEY ( group_id ) REFERENCES groups ( id )) #{post_fix}" + + db.do "INSERT INTO users (name,email,password_hash,password_salt) VALUES ('administrators','admin@user','$2a$10$H.w3ssI9KfuvNEXXp1qxD.b3Wm8alJG.HXviUofe4nErDn.TKUAka','$2a$10$H.w3ssI9KfuvNEXXp1qxD.')" + db.do "INSERT INTO groups (name, admin, description) VALUES ('admin','TRUE','')" + db.do "INSERT INTO user_groups (user_id, group_id) SELECT users.id,groups.id FROM users,groups WHERE users.email = 'admin@user' and groups.name = 'admin'" + + # PROJECTS + CommonProject.create_table(db, inc, post_fix) + GitBuildProject.create_table(db, post_fix) + BinaryUploadProject.create_table(db, post_fix) + db.do "CREATE TABLE group_project_accesses( + group_id INTEGER NOT NULL, + project_id INTEGER NOT NULL, + build VARCHAR(32) NOT NULL DEFAULT 'TRUE', + PRIMARY KEY ( group_id,project_id ), + CONSTRAINT fk_groups_has_projects_groups1 FOREIGN KEY ( group_id ) REFERENCES groups ( id ), + CONSTRAINT fk_groups_has_projects_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ) )#{post_fix}" + + # JOBS + CommonJob.create_table(db, post_fix) + end + + return result + end + + + def get_db_connection(transaction=true) + begin + if @db_dsn =~ /^SQLite3:/ then + @sqlite3_db_mutex.lock + @db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd) + else + if @db.nil? or not @db.connected? then + @db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd) + end + end + if transaction then + @db['AutoCommit'] = false + begin + @db.transaction do |dbh| + yield dbh if block_given? + end + ensure + @db['AutoCommit'] = true + end + else + yield @db if block_given? + end + + return true + + rescue DBI::DatabaseError => e + @log.error "DB loading failed!" if not @log.nil? + @log.error e.errstr if not @log.nil? + @log.error e.backtrace.inspect if not @log.nil? + + ensure + if @db_dsn =~ /^SQLite3:/ then + @db.disconnect if @db + @db = nil + @sqlite3_db_mutex.unlock + end + end + + return false + end + + + def check_user_id_from_email(user_email) + get_db_connection() do |db| + row = db.select_one("SELECT * FROM users WHERE email='#{user_email}'") + if not row.nil? then + return row['id'] + else + return -1 + end + end + + return -1 + end + + + def get_email_using_user_id(user_id) + get_db_connection() do |db| + row = db.select_one("SELECT * FROM users WHERE id='#{user_id}'") + if not row.nil? then + return row['email'] + else + return -1 + end + end + return -1 + end + + + def qualify_admin_to_access(prj_id) + # nothing to do, admin can change everything on web admin tool + end end diff --git a/src/build_server/BuildServerController.rb b/src/build_server/BuildServerController.rb index b0b237b..eabded1 100644 --- a/src/build_server/BuildServerController.rb +++ b/src/build_server/BuildServerController.rb @@ -1,5 +1,5 @@ =begin - + BuildServerController.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -34,7 +34,7 @@ class BuildServerController @@instance_map = {} # create - def self.create_server (id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id) + def self.create_server (id, path, ftpsvr_addr=nil, ftpsvr_port=nil, ftpsvr_username=nil, ftpsvr_passwd=nil) # check server config root check_build_server_root @@ -45,24 +45,20 @@ class BuildServerController end # create new instance and return it - @@instance_map[id] = BuildServer.new( id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id ) - + @@instance_map[id] = BuildServer.new( id, path, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd) # set default - @@instance_map[id].git_server_url="gerrithost:" - if Utils::HOST_OS == "windows" then + if Utils.is_windows_like_os(Utils::HOST_OS) then @@instance_map[id].git_bin_path="/c/Program\\ Files/Git/bin/git.exe" else @@instance_map[id].git_bin_path="/usr/bin/git" end - @@instance_map[id].allowed_git_branch=nil - @@instance_map[id].max_working_jobs= 2 - @@instance_map[id].job_log_url="" - @@instance_map[id].pkgsvr_cache_path="#{path}/pkgsvr_cache" - # write config write_server_config( @@instance_map[id] ) + # set logger + @@instance_map[id].log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{id}/log" ) + puts "Created new build server: \"#{id}\"" return @@instance_map[id] end @@ -78,31 +74,49 @@ class BuildServerController FileUtils.rm_rf "#{BuildServer::CONFIG_ROOT}/#{id}" @@instance_map[id] = nil puts "Removed the server \"#{id}\"" + else + puts "The server \"#{id}\" does not exist!" end - - # remove local package server - local_pkgsvr = PackageServer.new( id ) - local_pkgsvr.remove_server(id) + end + def self.migrate_server (id, dsn, user, passwd) + # set DB environment + server = get_server(id) + server.db_dsn = dsn if not dsn.nil? + server.db_user = user if not user.nil? + server.db_passwd = passwd if not passwd.nil? + + # check db + if migrate_db(server) then + write_server_config(server) + end end + def self.migrate_db (server) + version = server.get_dbversion + if version.nil? then server.create_db end + return server.db_upgrade + end # get def self.get_server( id ) # check instance first if not @@instance_map[id] == nil - return @@instance_map[id] + return @@instance_map[id] end - # check server config - if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{id}/server.cfg" - raise RuntimeError, "The server \"#{id}\" does not exist." + # check server config + if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{id}/server.cfg" + raise RuntimeError, "The server \"#{id}\" does not exist!" end # get server config and return its object @@instance_map[id] = read_server_config(id) + # set logger first + @@instance_map[id].log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{id}/log" ) + return @@instance_map[id] end @@ -110,24 +124,14 @@ class BuildServerController # start server def self.start_server( id, port = 2222 ) server = get_server(id) - - # write run port + migrate_db(server) + server.jobmgr.cancel_broken_status + + # write run port server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}" f = File.open( "#{server_dir}/run", "w" ) f.puts port - f.close - - # write run job - if File.exist? "#{server_dir}/latest_job" then - f = File.open( "#{server_dir}/latest_job", "r" ) - server.job_index = f.gets.strip.to_i + 1 - f.close - else - f = File.open( "#{server_dir}/latest_job", "w" ) - f.puts "0" - server.job_index = 0 - f.close - end + f.close # start server.port = port @@ -137,29 +141,141 @@ class BuildServerController # stop server def self.stop_server( id ) + + # server + server = get_server(id) + migrate_db(server) + client = BuildCommClient.create( "127.0.0.1", server.port ) + if client.nil? then + puts "Server is not running!" + return false + end + + # send request + stop_ok = false + if client.send "STOP|#{server.password}" then + # recevie & print + mismatched = false + result = client.read_lines do |l| + puts l + if l.include? "Password mismatched!" then + mismatched = true + end + end + if result and not mismatched then + stop_ok = true + end + end + + # terminate + client.terminate + + if not stop_ok then + puts "Server stop failed!" + end + + return true + end + + # upgrade server + def self.upgrade_server( id ) + + # server + server = get_server(id) + migrate_db(server) + client = BuildCommClient.create( "127.0.0.1", server.port ) + if client.nil? then + puts "Server is not running!" + return false + end + + # send request + upgrade_ok = false + if client.send "UPGRADE|#{server.password}" then + # recevie & print + mismatched = false + result = client.read_lines do |l| + puts l + if l.include? "Password mismatched!" then + mismatched = true + end + end + if result and not mismatched then + upgrade_ok = true + end + end + + # terminate + client.terminate + + if not upgrade_ok then + puts "Server upgrade failed!" + end + + return true + end + + # request upgrade friends build server + def self.request_upgrade_server( id ) + server = get_server(id) + migrate_db(server) + server_dir = "#{BuildServer::CONFIG_ROOT}/#{id}" + + if File.exist? "#{server_dir}/friends" then + File.open( "#{server_dir}/friends", "r" ) do |f| + f.each_line do |l| + if l.split(",").count < 2 then next end + ip = l.split(",")[0].strip + port = l.split(",")[1].strip - # if the server is not running => error + client = BuildCommClient.create( ip, port ) + if client.nil? then + puts "Friend Server #{ip}:#{port} is not running!" + next + end + # send request + upgrade_ok = false + if client.send "UPGRADE|#{server.password}" then + # recevie & print + mismatched = false + result = client.read_lines do |l2| + puts l2 + if l2.include? "Password mismatched!" then + mismatched = true + end + end + if result and not mismatched then + upgrade_ok = true + end + end + + # terminate + client.terminate + + if upgrade_ok then + puts "Friend Server #{ip}:#{port} upgrade requested!" + else + puts "Friend Server #{ip}:#{port} upgrade failed!" + end + end + end + else + puts "No Friend Server." + end - # request stop + return true end # add friend server - def self.add_friend_server( id, ip, port ) + def self.add_remote_server( id, ip, port ) server = get_server(id) - + migrate_db(server) + # add - if server.add_friend_server( ip, port ) then - - # write config - server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}" - f = File.open( "#{server_dir}/friends", "a" ) - f.puts "#{ip},#{port}" - f.close - + if server.add_remote_server( ip, port ) then puts "Friend server is added successfully!" - return true else puts "Friend server already exists in list!" @@ -168,87 +284,538 @@ class BuildServerController end - # build git repository and upload - def self.build_git( id, repository, commit, os, url, resolve ) + # remove friend server + def self.remove_remote_server( id, ip, port ) + server = get_server(id) + migrate_db(server) - # server + # add + if server.remove_remote_server( ip, port ) then + puts "Friend server is removed successfully!" + return true + else + puts "Friend server does not exist in list!" + return false + end + end + + + # add supported target os + def self.add_target_os( id, os_name ) + # get server server = get_server(id) - client = BuildCommClient.create( "127.0.0.1", server.port ) - if client.nil? then return false end + migrate_db(server) - # send request - client.send "BUILD,GIT,#{repository},#{commit},#{os}" + # add + if server.add_supported_os( os_name ) then + puts "Target OS is added successfully!" + return true + else + puts "Target OS already exists in list!" + return false + end + end - # recevie & print - client.print_stream - # terminate - client.terminate + # remove supported target os + def self.remove_target_os( id, os_name ) + # get server + server = get_server(id) + migrate_db(server) - return true + # add + if server.remove_supported_os( os_name ) then + puts "Target OS is removed successfully!" + return true + else + puts "Target OS does not exist in list!" + return false + end + + server.quit end - # resolve git and build it and upload - def resolve_git( id, repository, commit, os, url ) - # server + # add distribution + def self.add_distribution( id, dist_name, pkgsvr_url, pkgsvr_ip, pkgsvr_port ) + # get server server = get_server(id) - client = BuildCommClient.create( "127.0.0.1", server.port ) - if client.nil? then return false end + migrate_db(server) - # send request - client.send "RESOLVE,GIT,#{repository},#{commit},#{os}" + # add + if server.distmgr.add_distribution( dist_name, pkgsvr_url, pkgsvr_ip, pkgsvr_port ) then + puts "Distribution is added successfully!" + return true + else + puts "Distribution already exists in list!" + return false + end + end - # recevie & print - client.print_stream - # terminate - client.terminate + # remove distribution + def self.remove_distribution( id, dist_name ) + # get server + server = get_server(id) + migrate_db(server) - return true + # remove + if server.distmgr.remove_distribution( dist_name ) then + puts "Distribution is removed successfully!" + return true + else + puts "Distribution does not exist in list!" + return false + end + end + + + # lock distribution + def self.lock_distribution(id, dist_name) + # get server + server = get_server(id) + migrate_db(server) + + # remove + if server.distmgr.set_distribution_lock(dist_name, true) then + puts "Distribution is locked!" + return true + else + puts "Locking distribution failed!" + return false + end + end + + + # unlock distribution + def self.unlock_distribution(id, dist_name) + # get server + server = get_server(id) + migrate_db(server) + + # remove + if server.distmgr.set_distribution_lock(dist_name, false) then + puts "Distribution is unlocked!" + return true + else + puts "Unlocking distribution failed!" + return false + end + end + + + # add remote package server + def self.add_sync_package_server(id, url, dist_name) + server = get_server(id) + migrate_db(server) + + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + + # add + if server.add_sync_package_server( url, dist_name ) then + puts "Remote package server is added!" + return true + else + puts "The server already exists in list!" + return false + end + end + + + def self.check_distribution_name(dist_name, server) + if (dist_name.nil? or dist_name.empty?) then + dist_name = server.distmgr.get_default_distribution_name() + end + if dist_name.nil? or dist_name.empty? then + puts "No distribution is defined!" + return nil + end + + return dist_name + end + + # remove remote package server + def self.remove_sync_package_server(id, url, dist_name) + server = get_server(id) + migrate_db(server) + + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + + # remove + if server.remove_sync_package_server( url, dist_name ) then + puts "Remote package server is removed!" + return true + else + puts "The server does not exist in list!" + return false + end + end + + + # add project + def self.add_project( id, project_name, git_repos, git_branch, remote_server_id, + passwd, os_string, dist_name ) + # get server + server = get_server(id) + migrate_db(server) + + # get supported os for project. + # if not specified, all supported os of the server will be used + if os_string.nil? or os_string.empty? then + os_list = server.supported_os_list + else + os_list = os_string.strip.split(",") + + # check OS name + os_list.each do |os| + if not server.supported_os_list.include? os then + puts "Unsupported OS name \"#{os}\" is used!" + puts "Check the following supported OS list:" + server.supported_os_list.each do |s_os| + puts " * #{s_os}" + end + + return false + end + end + end + + # add + if git_repos.nil? or git_branch.nil? then + puts "Git repository or branch must be specified!" + return false + end + + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + + result = server.prjmgr.add_git_project( project_name, git_repos, git_branch, passwd, os_list, dist_name ) + if result then + puts "Adding project succeeded!" + return true + else + puts "Adding project failed!" + return false + end + end + + + # add binary project + def self.add_binary_project( id, project_name, pkg_name, passwd, os_string, dist_name ) + # get server + server = get_server(id) + migrate_db(server) + + # get supported os for project. + # if not specified, all supported os of the server will be used + if os_string.nil? or os_string == "default" then + os_list = server.supported_os_list + else + os_list = os_string.strip.split(",") + # check OS name + os_list.each do |os| + if not server.supported_os_list.include? os then + puts "Unsupported OS name \"#{os}\" is used!" + puts "Check the following supported OS list:" + server.supported_os_list.each do |s_os| + puts " * #{s_os}" + end + + return false + end + end + end + + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + + # add + result = server.prjmgr.add_binary_project( project_name, pkg_name, passwd, + os_list, dist_name ) + if result then + puts "Adding project succeeded!" + return true + else + puts "Adding project failed!" + return false + end + end + + + # remove project + def self.remove_project( id, project_name, dist_name ) + # get server + server = get_server(id) + migrate_db(server) + + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + + result = server.prjmgr.remove_project( project_name, dist_name ) + if result then + puts "Removing project succeeded!" + return true + else + puts "Removing project failed!" + return false + end end - # build local project and upload - def self.build_local( id, local_path, os, url, resolve ) + # full build + def self.build_all_projects( id, dist_name ) + # server server = get_server(id) + migrate_db(server) + + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + client = BuildCommClient.create( "127.0.0.1", server.port ) - if client.nil? then return false end + if client.nil? then + puts "Server is not running!" + return false + end # send request - client.send "BUILD,LOCAL,#{local_path},#{os}" - - # recevie & print - client.print_stream + fullbuild_ok = false + if client.send "FULLBUILD|#{server.password}|#{dist_name}" then + # recevie & print + mismatched = false + dist_not_found = false + result = client.read_lines do |l| + puts l + if l.include? "Password mismatched!" then + mismatched = true + end + if l.include? "Distribution not found!" then + dist_not_found = true + end + end + if result and not mismatched and not dist_not_found then + fullbuild_ok = true + end + end - # terminate + # terminate client.terminate + if not fullbuild_ok then + puts "Full build failed!" + end + return true end - # resolve local project and build it and upload - def resolve_local( path, os ) + def self.register_package(id, file_path, dist_name) # server server = get_server(id) - client = BuildCommClient.create( "127.0.0.1", server.port ) - if client.nil? then return false end + migrate_db(server) - # send request - client.send "RESOLVE,LOCAL,#{local_path},#{os}" + # check distribution + dist_name = check_distribution_name(dist_name, server) + if dist_name.nil? then return false end + + # check file exist? + if not File.exist? file_path then + puts "File not found!" + return false + end + file_path = File.expand_path(file_path) - # recevie & print - client.print_stream + # send request + success = false + client = BuildCommClient.create( "127.0.0.1", server.port ) + if client.nil? then + puts "Server is not running!" + return false + end + if client.send "REGISTER|BINARY-LOCAL|#{file_path}|#{server.password}|#{dist_name}" then + # recevie & print + mismatched = false + result = client.read_lines do |l| + puts l + if l.include? "Password mismatched!" then + mismatched = true + end + end + if result and not mismatched then + success = true + end + end - # terminate + # terminate client.terminate + if not success then + puts "Registering package failed!" + end + return true end + # server + def self.query_server( id ) + server = get_server(id) + migrate_db(server) + server.prjmgr.load() + + puts "* REMOTE SERVER(S) *" + server.get_remote_servers.each do |s| + puts " * #{s.ip}:#{s.port}" + end + puts "" + + puts "* SUPPORTED OS *" + server.supported_os_list.each do |os| + puts " * #{os}" + end + puts "" + + puts "* DISTRIBUTION(S) *" + server.distmgr.get_all_distributions().each do |d| + puts " * #{d.name}" + end + puts "" + + puts "* SYNC PACKAGE SERVER(S) *" + server.get_sync_package_servers.each do |s| + puts " * [#{s[1]}] #{s[0]}" + end + puts "" + + puts "* PROJECT(S) *" + server.prjmgr.get_all_projects().each do |p| + puts " * [#{p.dist_name}] #{p.name}" + end + end + + + # server + def self.set_server_attribute( id, attr, value ) + result = true + + if attr.nil? or attr.empty? or value.nil? or value.empty? then + puts "Attribute/Value must be specified!" + return false + end + + server = get_server(id) + case attr + when "GIT_BIN_PATH" + server.git_bin_path = value + when "MAX_WORKING_JOBS" + server.jobmgr.max_working_jobs = value.to_i + when "JOB_LOG_URL" + server.job_log_url = value + when "SEND_MAIL" + server.send_mail = value + when "TEST_TIME" + server.test_time = value.to_i + when "PASSWORD" + server.password = value + when "JOB_KEEP_TIME" + server.keep_time = value.to_i + when "FTP_ADDR" + server.ftp_addr = value + when "FTP_PORT" + server.ftp_port = value + when "FTP_USERNAME" + server.ftp_username = value + when "FTP_PASSWD" + server.ftp_passwd = value + when "CHANGELOG_CHECK" + server.changelog_check = value + when "DB_DSN" + case value + when /^SQLite3:(.*)/i then + if $1.strip.empty? then db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db" + else db_dsn = "SQLite3:#{$1.strip}" + end + when /^Mysql:(.*)/i then + db_dsn = "Mysql:#{$1}" + else + db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db" + end + server.db_dsn = db_dsn + when "DB_USER" + server.db_user = value if not value.empty? + when "DB_PASSWORD" + server.db_passwd = value if not value.empty? + else + puts "Wrong attribute name!" + result = false + end + + if result then write_server_config( server ) end + + return result + end + + + # server + def self.get_server_attribute( id, attr ) + result = true + + if attr.nil? or attr.empty? then + puts "Attribute name must be specified!" + return false + end + + server = get_server(id) + case attr + when "GIT_BIN_PATH" + puts server.git_bin_path + when "MAX_WORKING_JOBS" + puts server.jobmgr.max_working_jobs + when "JOB_LOG_URL" + puts server.job_log_url + when "SEND_MAIL" + puts server.send_mail + when "TEST_TIME" + puts server.test_time + when "PASSWORD" + puts server.password + when "JOB_KEEP_TIME" + puts server.keep_time + when "FTP_ADDR" + puts server.ftp_addr + when "FTP_PORT" + puts server.ftp_port + when "FTP_USERNAME" + puts server.ftp_username + when "FTP_PASSWD" + puts server.ftp_passwd + when "CHANGELOG_CHECK" + puts server.changelog_check + when "DB_DSN" + puts server.db_dsn + when "DB_USER" + puts server.db_user + when "DB_PASSWORD" + puts server.db_passwd + else + puts "Wrong attribute name!" + result = false + end + + return result + end + + + ##################### private + ##################### # check build server config path def self.check_build_server_root @@ -264,21 +831,24 @@ class BuildServerController def self.write_server_config( server ) # create config folder server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}" - FileUtils.mkdir_p( "#{server_dir}" ) + if not File.exist? server_dir then + FileUtils.mkdir_p( server_dir ) + end # write configuration File.open( "#{server_dir}/server.cfg", "w" ) do |f| f.puts "ID=#{server.id}" f.puts "PATH=#{server.path}" - f.puts "PSERVER_URL=#{server.pkgserver_url}" - f.puts "PSERVER_ADDR=#{server.pkgserver_addr}" - f.puts "PSERVER_ID=#{server.pkgserver_id}" - f.puts "PSERVER_CACHE_PATH=#{server.pkgsvr_cache_path}" - f.puts "GIT_SERVER_URL=#{server.git_server_url}" f.puts "GIT_BIN_PATH=#{server.git_bin_path}" - f.puts "ALLOWED_GIT_BRANCH=#{server.allowed_git_branch}" - f.puts "MAX_WORKING_JOBS=#{server.max_working_jobs}" - f.puts "JOB_LOG_URL=#{server.job_log_url}" + f.puts "TEST_TIME=#{server.test_time}" if server.test_time > 0 + f.puts "PASSWORD=#{server.test_time}" if server.password != "0000" + if not server.ftp_addr.nil? then + f.puts "FTP_URL=ftp://#{server.ftp_username}:#{server.ftp_passwd}@#{server.ftp_addr}:#{server.ftp_port}" + end + f.puts "#only supports \"Mysql\" and \"SQLite3\"" + f.puts "DB_DSN=#{server.db_dsn}" + f.puts "DB_USER=#{server.db_user}" + f.puts "DB_PASSWORD=#{server.db_passwd}" end end @@ -286,48 +856,62 @@ class BuildServerController # read server configuration def self.read_server_config( id ) path="" - pkgsvr_url="" - pkgsvr_addr="" - pkgsvr_id="" - pkgsvr_cache_path="" - git_server_url="gerrithost:" git_bin_path="/usr/bin/git" - allowed_git_branch="" - max_working_jobs= 2 - job_log_url="" + test_time=0 + password="0000" + ftp_addr=nil + ftp_port=nil + ftp_username=nil + ftp_passwd=nil + db_dsn="SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db" + db_user=nil + db_passwd=nil # read configuration server_dir = "#{BuildServer::CONFIG_ROOT}/#{id}" File.open( "#{server_dir}/server.cfg", "r" ) do |f| f.each_line do |l| + if l.strip.start_with?("#") then next end + idx = l.index("=") + 1 + length = l.length - idx + if l.start_with?("PATH=") - path = l.split("=")[1].strip - elsif l.start_with?("PSERVER_URL=") - pkgsvr_url = l.split("=")[1].strip - elsif l.start_with?("PSERVER_ADDR=") - pkgsvr_addr = l.split("=")[1].strip - elsif l.start_with?("PSERVER_ID=") - pkgsvr_id = l.split("=")[1].strip - elsif l.start_with?("PSERVER_CACHE_PATH=") - pkgsvr_cache_path = l.split("=")[1].strip - elsif l.start_with?("GIT_SERVER_URL=") - git_server_url = l.split("=")[1].strip + path = l[idx,length].strip elsif l.start_with?("GIT_BIN_PATH=") - git_bin_path = l.split("=")[1].strip - elsif l.start_with?("ALLOWED_GIT_BRANCH=") - allowed_git_branch = l.split("=")[1].strip - elsif l.start_with?("MAX_WORKING_JOBS=") - max_working_jobs = l.split("=")[1].strip.to_i - elsif l.start_with?("JOB_LOG_URL=") - job_log_url = l.split("=")[1].strip + git_bin_path = l[idx,length].strip + elsif l.start_with?("TEST_TIME=") + test_time = l[idx,length].strip.to_i + elsif l.start_with?("PASSWORD=") + password = l[idx,length].strip.to_i + elsif l.start_with?("FTP_URL=") + ftp_result = Utils.parse_ftpserver_url(l[idx,length].strip) + ftp_addr = ftp_result[0] + ftp_port = ftp_result[1] + ftp_username = ftp_result[2] + ftp_passwd = ftp_result[3] + elsif l.start_with?("DB_DSN=") + case l[idx,length].strip + when /^SQLite3:(.*)/i then + if $1.strip.empty? then db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db" + else db_dsn = "SQLite3:#{$1.strip}" + end + when /^Mysql:(.*)/i then + db_dsn = "Mysql:#{$1}" + else + db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db" + end + elsif l.start_with?("DB_USER=") + db_user = l[idx,length].strip if not l[idx,length].strip.empty? + elsif l.start_with?("DB_PASSWORD=") + db_passwd = l[idx,length].strip if not l[idx,length].strip.empty? else - next - end + next + end end end # create server object - obj = BuildServer.new( id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id ) + obj = BuildServer.new( id, path, ftp_addr, ftp_port, ftp_username, ftp_passwd ) # check running port if File.exist? "#{server_dir}/run" then @@ -337,40 +921,23 @@ class BuildServerController f.close end - # check friend server - if File.exist? "#{server_dir}/friends" then - File.open( "#{server_dir}/friends", "r" ) do |f| - f.each_line do |l| - if l.split(",").count < 2 then next end - ip = l.split(",")[0].strip - port = l.split(",")[1].strip - obj.add_friend_server( ip, port.to_i ) - end - end - end - - # set git server url - obj.git_server_url = git_server_url - # set git binary path obj.git_bin_path = git_bin_path - - # set git binary path - obj.max_working_jobs = max_working_jobs - # set job log url - obj.job_log_url = job_log_url + # set test time + obj.test_time = test_time - # set allowed git branch name - obj.allowed_git_branch = allowed_git_branch + # set password + obj.password = password - # set package server path - pkgsvr_cache_path = (pkgsvr_cache_path.empty? ? "#{path}/pkgsvr_cache":pkgsvr_cache_path) - obj.pkgsvr_cache_path= pkgsvr_cache_path + # DB settring + obj.db_dsn = db_dsn if not db_dsn.nil? + obj.db_user = db_user + obj.db_passwd = db_passwd # save config - write_server_config( obj ) - + #write_server_config( obj ) + # create object & return it return obj end diff --git a/src/build_server/BuildServerException.rb b/src/build_server/BuildServerException.rb new file mode 100644 index 0000000..8faed9a --- /dev/null +++ b/src/build_server/BuildServerException.rb @@ -0,0 +1,31 @@ +class BuildServerException < Exception + @@err_msgs = { + "ERR001" => "Invalid request format is used!", + "ERR002" => "Distribution not found!", + "ERR003" => "Unsupported OS name used!", + "ERR004" => "User account not found!", + "ERR005" => "Project access denied!", + "ERR006" => "Job creation failed!", + "ERR007" => "No supported OS defined in build server!", + "ERR008" => "Distribution locked!", + "ERR009" => "Project not found!", + "ERR010" => "Build operation not allowed on this project type!", + "ERR011" => "Project password required!", + "ERR012" => "Project password not matched!", + "ERR013" => "Project from file-name/distribution not found!", + "ERR014" => "Job cancel failed!", + "ERR015" => "Server password not matched!" + } + + def initialize(code) + @err_code = code + end + + def err_message() + if not message().nil? and not message().empty? then + return "Error: #{@@err_msgs[@err_code]}: #{message()}" + else + return "Error: #{@@err_msgs[@err_code]}" + end + end +end diff --git a/src/build_server/BuildServerOptionParser.rb b/src/build_server/BuildServerOptionParser.rb index 55fc370..455a48b 100644 --- a/src/build_server/BuildServerOptionParser.rb +++ b/src/build_server/BuildServerOptionParser.rb @@ -1,5 +1,5 @@ =begin - + BuildServerOptionParser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -26,92 +26,366 @@ Contributors: - S-Core Co., Ltd =end +$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common" require 'optparse' +require 'utils' + +class BuildServerUsage + CREATE="build-svr create -n [-t ]" + REMOVE="build-svr remove -n " + MIGRATE="build-svr migrate -n [--dsn [--dbuser --dbpassword ] ]" + START="build-svr start -n -p " + STOP="build-svr stop -n " + UPGRADE="build-svr upgrade -n [-D ]" + ADD_SVR="build-svr add-svr -n -d " + REMOVE_SVR= "build-svr remove-svr -n -d " + ADD_OS= "build-svr add-os -n -o " + REMOVE_OS="build-svr remove-os -n -o " + ADD_DIST= "build-svr add-dist -n -D -u -d " + REMOVE_DIST="build-svr remove-dist -n -D " + LOCK_DIST="build-svr lock-dist -n -D " + UNLOCK_DIST="build-svr unlock-dist -n -D " + ADD_SYNC="build-svr add-sync -n -u [--dist ]" + REMOVE_SYNC="build-svr remove-sync -n -u [--dist ]" + ADD_PRJ="build-svr add-prj -n -N (-g -b |-P ) [-w ] [-o ] [--dist ]" + REMOVE_PRJ="build-svr remove-prj -n -N [--dist ]" + FULLBUILD="build-svr fullbuild -n [--dist ]" + REGISTER="build-svr register -n -P [--dist ]" + QUERY="build-svr query -n " + SET_ATTR="build-svr set-attr -n -A -V " + GET_ATTR="build-svr get-attr -n -A " +end + +def option_error_check( options ) + case options[:cmd] + + when "create" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::CREATE + end + + when "remove" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE + end + + when "migrate" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::MIGRATE + end + + when "start" + if options[:name].nil? or options[:name].empty? or + options[:port].nil? then + raise ArgumentError, "Usage: " + BuildServerUsage::START + end + + when "stop" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::STOP + end + + when "upgrade" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::UPGRADE + end + + when "add-svr" + if options[:name].nil? or options[:name].empty? or + (options[:domain].nil? or options[:domain].empty?) then + raise ArgumentError, "Usage: " + BuildServerUsage::ADD_SVR + end + + when "remove-svr" + if options[:name].nil? or options[:name].empty? or + (options[:domain].nil? or options[:domain].empty?) then + raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_SVR + end + + when "add-os" + if options[:name].nil? or options[:name].empty? or + options[:os].nil? or options[:os].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::ADD_OS + end + + when "remove-os" + if options[:name].nil? or options[:name].empty? or + options[:os].nil? or options[:os].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_OS + end + + when "add-dist" + if options[:name].nil? or options[:name].empty? or + options[:dist].nil? or options[:dist].empty? or + options[:url].nil? or options[:url].empty? or + options[:domain].nil? or options[:domain].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::ADD_DIST + end + + when "remove-dist" + if options[:name].nil? or options[:name].empty? or + options[:dist].nil? or options[:dist].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_DIST + end + + when "lock-dist" + if options[:name].nil? or options[:name].empty? or + options[:dist].nil? or options[:dist].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::LOCK_DIST + end + + when "unlock-dist" + if options[:name].nil? or options[:name].empty? or + options[:dist].nil? or options[:dist].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::UNLOCK_DIST + end + + when "add-sync" + if options[:name].nil? or options[:name].empty? or + (options[:url].nil? or options[:url].empty?) then + raise ArgumentError, "Usage: " + BuildServerUsage::ADD_SYNC + end + + when "remove-sync" + if options[:name].nil? or options[:name].empty? or + (options[:url].nil? or options[:url].empty?) then + raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_SYNC + end + + when "add-prj" + if options[:name].nil? or options[:name].empty? or + options[:pid].nil? or options[:pid].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::ADD_PRJ + end + + when "remove-prj" + if options[:name].nil? or options[:name].empty? or + options[:pid].nil? or options[:pid].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_PRJ + end + + when "fullbuild" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::FULLBUILD + end + + when "register" + if options[:name].nil? or options[:name].empty? or + options[:package].nil? or options[:package].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::REGISTER + end + + when "query" + if options[:name].nil? or options[:name].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::QUERY + end + + when "set-attr" + if options[:name].nil? or options[:name].empty? or + options[:attr].nil? or options[:attr].empty? or + options[:value].nil? or options[:value].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::SET_ATTR + end + + when "get-attr" + if options[:name].nil? or options[:name].empty? or + options[:attr].nil? or options[:attr].empty? then + raise ArgumentError, "Usage: " + BuildServerUsage::SET_ATTR + end -def option_parse - options = {} - banner = "Usage: build-svr {create|remove|start|build|help} ..." + "\n" \ - + "\t" + "build-svr create -n -u -d -i " + "\n" \ - + "\t" + "build-svr remove -n " + "\n" \ - + "\t" + "build-svr start -n [-p [-l ] [-g -c ] [-o ] [-r]" + "\n" \ - + "\t" + "build-svr add -n [-d -p ]" + "\n" - - optparse = OptionParser.new do|opts| - # Set a banner, displayed at the top - # of the help screen. - - opts.banner = banner - - opts.on( '-n', '--name ', 'build server name' ) do|name| - options[:name] = name - end - - opts.on( '-u', '--url ', 'package server URL: http://xxx/yyy/zzz' ) do|url| - options[:url] = url - end - - opts.on( '-d', '--domain ', 'package svr or friend svr ip or ssh alias' ) do|domain| - options[:domain] = domain - end - - opts.on( '-i', '--id ', 'package server id' ) do|pid| - options[:pid] = pid - end - - options[:port] = 2222 - opts.on( '-p', '--port ', 'port' ) do|port| - options[:port] = port.strip.to_i - end - - opts.on( '-l', '--local ', 'local source path' ) do|path| - options[:local] = path - end - - opts.on( '-g', '--git ', 'git repository gerrithost:/xxx/yyy/zzz' ) do|git| - options[:git] = git - end - - opts.on( '-c', '--commit ', 'git commit id/tag' ) do|git| - if git.start_with? "/" then - git = git[1..-1] - end - options[:commit] = git - end - - opts.on( '-o', '--os ', 'target operating system linux/windows/darwin' ) do|os| - options[:os] = os - end - - options[:resolve] = false - opts.on( '-r', '--resolve', 'reverse build dependency fail resolve' ) do - options[:resolve] = true - end + else + raise ArgumentError, "Input is incorrect : #{options[:cmd]}" + end +end + +def option_parse + options = {} + banner = "Build-server administer service command-line tool." + "\n" \ + + "\n" + "Usage: build-svr [OPTS] or build-svr (-h|-v)" + "\n" \ + + "\n" + "Subcommands:" + "\n" \ + + "\t" + "create Create the build-server." + "\n" \ + + "\t" + "remove Remove the build-server." + "\n" \ + + "\t" + "migrate build-server DB migrate." + "\n" \ + + "\t" + "start Start the build-server." + "\n" \ + + "\t" + "stop Stop the build-server." + "\n" \ + + "\t" + "upgrade Upgrade the build-server include friends." + "\n" \ + + "\t" + "add-svr Add remote build/package server for support multi-OS or distribute build job." + "\n" \ + + "\t" + "remove-svr Remove remote build/package server for support multi-OS or distribute build job." + "\n" \ + + "\t" + "add-os Add supported OS." + "\n" \ + + "\t" + "remove-os Remove supported OS." + "\n" \ + + "\t" + "add-dist Add distribution." + "\n" \ + + "\t" + "remove-dist Remove distribution." + "\n" \ + + "\t" + "lock-dist Lock distribution." + "\n" \ + + "\t" + "unlock-dist Unlock distribution." + "\n" \ + + "\t" + "add-sync Add package repository URL to synchronize with." + "\n" \ + + "\t" + "remove-sync Remove package repository URL." + "\n" \ + + "\t" + "add-prj Add project to build." + "\n" \ + + "\t" + "remove-prj Remove project." + "\n" \ + + "\t" + "register Register the package to the build-server." + "\n" \ + + "\t" + "fullbuild Build all your projects and upload them to package server." + "\n" \ + + "\t" + "query Show build server configuration." + "\n" \ + + "\t" + "set-attr Set build server atribute." + "\n" \ + + "\t" + "get-attr Get build server atribute." + "\n" \ + + "\n" + "Subcommand usage:" + "\n" \ + + "\t" + BuildServerUsage::CREATE + "\n" \ + + "\t" + BuildServerUsage::REMOVE + "\n" \ + + "\t" + BuildServerUsage::MIGRATE + "\n" \ + + "\t" + BuildServerUsage::START + "\n" \ + + "\t" + BuildServerUsage::STOP + "\n" \ + + "\t" + BuildServerUsage::UPGRADE + "\n" \ + + "\t" + BuildServerUsage::ADD_SVR + "\n" \ + + "\t" + BuildServerUsage::REMOVE_SVR + "\n" \ + + "\t" + BuildServerUsage::ADD_OS + "\n" \ + + "\t" + BuildServerUsage::REMOVE_OS + "\n" \ + + "\t" + BuildServerUsage::ADD_DIST + "\n" \ + + "\t" + BuildServerUsage::REMOVE_DIST + "\n" \ + + "\t" + BuildServerUsage::LOCK_DIST + "\n" \ + + "\t" + BuildServerUsage::UNLOCK_DIST + "\n" \ + + "\t" + BuildServerUsage::ADD_SYNC + "\n" \ + + "\t" + BuildServerUsage::REMOVE_SYNC + "\n" \ + + "\t" + BuildServerUsage::ADD_PRJ + "\n" \ + + "\t" + BuildServerUsage::REMOVE_PRJ + "\n" \ + + "\t" + BuildServerUsage::FULLBUILD + "\n" \ + + "\t" + BuildServerUsage::REGISTER + "\n" \ + + "\t" + BuildServerUsage::QUERY + "\n" \ + + "\t" + BuildServerUsage::SET_ATTR + "\n" \ + + "\t" + BuildServerUsage::GET_ATTR + "\n" \ + + "\n" + "Options:" + "\n" + + optparse = OptionParser.new(nil, 32, ' '*8) do|opts| + # Set a banner, displayed at the top + # of the help screen. + + opts.banner = banner + + opts.on( '-n', '--name ', 'build server name' ) do|name| + options[:name] = name + end + + opts.on( '-u', '--url ', 'package server url: http://127.0.0.1/dibs/unstable' ) do|url| + options[:url] = url + end + + opts.on( '-d', '--address ', 'server address: 127.0.0.1:2224' ) do|domain| + options[:domain] = domain + end + + options[:port] = 2222 + opts.on( '-p', '--port ', 'server port number: 2224' ) do|port| + options[:port] = port.strip.to_i + end + + opts.on( '-P', '--pkg ', 'package file path or name' ) do|package| + options[:package] = package.strip + end + + options[:os] = nil + opts.on( '-o', '--os ', 'ex) ubuntu-32,windows-32' ) do|os| + if not Utils.multi_argument_test( os, "," ) then + raise ArgumentError, "OS variable parsing error : #{os}" + end + options[:os] = os + end + + opts.on( '-N', '--pname ', 'project name' ) do|pid| + options[:pid] = pid + end + + opts.on( '-g', '--git ', 'git repository' ) do|git| + options[:git] = git + end + + opts.on( '-b', '--branch ', 'git branch' ) do|branch| + options[:branch] = branch + end + + #opts.on( '-r', '--remote ', 'remote server id' ) do|remote| + # options[:remote] = remote + #end + options[:dist] = "" + opts.on( '-D', '--dist ', 'distribution name' ) do |dist| + options[:dist] = dist + end + + + options[:passwd] = "" + opts.on( '-w', '--passwd ', 'password for managing project' ) do|passwd| + options[:passwd] = passwd + end + + opts.on( '-t', '--ftp ', 'ftp server url: ftp://dibsftp:dibsftp@127.0.0.1:1024' ) do|domain| + options[:fdomain] = domain + end + + opts.on( '-A', '--attr ', 'attribute' ) do |attr| + options[:attr] = attr + end + + options[:db_dsn] = nil + opts.on( '--dsn ', 'Data Source Name ex) mysql:host=localhost;database=test' ) do |dsn| + options[:db_dsn] = dsn + end + + options[:db_user] = nil + opts.on( '--dbuser ', 'DB user id' ) do |user| + options[:db_user] = user + end + + options[:db_passwd] = nil + opts.on( '--dbpassword ', 'DB password' ) do |password| + options[:db_passwd] = password + end + + + opts.on( '-V', '--value ', 'value' ) do |value| + options[:value] = value + end opts.on( '-h', '--help', 'display this information' ) do - puts opts + opts.help.split("\n").each {|op| puts op if not op.include? "--CHILD"} + exit + end + + opts.on( '-v', '--version', 'display version' ) do + puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version() exit - end - - end - - cmd = ARGV[0] + end + + opts.on( '-C', '--CHILD', 'child process' ) do + options[:child] = true + end - if cmd.eql? "create" or cmd.eql? "remove" or cmd.eql? "start" or - cmd.eql? "build" or cmd.eql? "add" or - cmd =~ /(help)|(-h)|(--help)/ then + end - if cmd.eql? "help" then - ARGV[0] = "-h" + cmd = ARGV[0] + if cmd.eql? "create" or cmd.eql? "remove" or + cmd.eql? "start" or cmd.eql? "upgrade" or + cmd.eql? "stop" or cmd.eql? "migrate" or + cmd.eql? "add-svr" or cmd.eql? "remove-svr" or + cmd.eql? "add-os" or cmd.eql? "remove-os" or + cmd.eql? "add-dist" or cmd.eql? "remove-dist" or + cmd.eql? "lock-dist" or cmd.eql? "unlock-dist" or + cmd.eql? "add-sync" or cmd.eql? "remove-sync" or + cmd.eql? "add-prj" or cmd.eql? "remove-prj" or + cmd.eql? "fullbuild" or cmd.eql? "register" or + cmd.eql? "query" or + cmd.eql? "set-attr" or cmd.eql? "get-attr" or + cmd =~ /(-v)|(--version)/ or + cmd =~ /(help)|(-h)|(--help)/ then + + if cmd.eql? "help" then + ARGV[0] = "-h" end - options[:cmd] = ARGV[0] - else - raise ArgumentError, banner - end + options[:cmd] = ARGV[0] + else + raise ArgumentError, "Usage: build-svr [OPTS] or build-svr -h" + end + + optparse.parse! + + option_error_check options - optparse.parse! - - return options -end + return options +end diff --git a/src/build_server/CommonJob.rb b/src/build_server/CommonJob.rb new file mode 100644 index 0000000..5a624df --- /dev/null +++ b/src/build_server/CommonJob.rb @@ -0,0 +1,277 @@ +=begin + + CommonJob.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "fileutils" +require "time" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "utils.rb" + +class CommonJob + + attr_accessor :id, :server, :log, :status, :priority + attr_accessor :os, :type, :pre_jobs, :user_id + USER_JOB_PRIORITY = 100 + AUTO_JOB_PRIORITY = 0 + + # initialize + public + def initialize(server, id=nil) + @server = server + if not server.jobmgr.nil? then + @id = server.jobmgr.get_new_job_id() + else + @id = 0 + end + + @parent = nil + @sub_jobs = [] + @priority = USER_JOB_PRIORITY # higher numbered job get priority + @os = "Unknown" + @type = "Unknown" + @pre_jobs = [] #pre-requisite jobs + @project = nil + @user_id = 1 + + @status = "JUST_CREATED" + @log = nil + + @start_time = Time.now + @end_time = nil + + @sub_pid = 0 + end + + + # set parent + public + def set_parent_job( parent ) + @parent = parent + end + + + # get parent + public + def get_parent_job() + return @parent + end + + + # check this job has a parent job + public + def is_sub_job? + return (not @parent.nil?) + end + + + # get all sub jobs + public + def get_sub_jobs + return @sub_jobs + end + + + # add sub job + public + def add_sub_job( job ) + @sub_jobs.push job + # this will make sub-job to share build-root of parent + job.set_parent_job( self ) + end + + + # create logger + public + def create_logger( second_out, verbose = false ) + @log = JobLog.new( self, second_out, verbose ) + return @log + end + + + public + def get_project() + return @project + end + + + public + def set_project( project ) + @project = project + end + + public + def get_user_email + return @server.get_email_using_user_id(@user_id) + end + + + # execute + public + def execute(sync=false) + + # create a thread for job + @thread = Thread.new do + begin + job_main() + + # parent job will call sub job's terminate method + if not is_sub_job? then terminate() end + rescue => e + @log.error e.message + @log.error e.backtrace.inspect + end + end + + if sync then + @thread.join + end + + return true + end + + + #terminate + public + def terminate() + #do noting + end + + + #cancel + public + def cancel() + # kill sub process if exist? + kill_sub_process() + end + + + # show progress + public + def progress + # do nothing + return "" + end + + + # create process to execute command + public + def execute_command(cmd) + # execute + pid, status = Utils.execute_shell_with_log(cmd, @log.path, false) + @sub_pid = pid + + # wait for finish + begin + pid, status = Process.waitpid2(pid) + rescue Errno::ECHILD + # pid is not exist + # do notting + end + @sub_pid = 0 + + # return + return pid, status + end + + + public + def self.create_table(db, post_fix) + db.do "CREATE TABLE jobs ( + id INTEGER PRIMARY KEY, + project_id INTEGER, + user_id INTEGER NOT NULL, + supported_os_id INTEGER, + distribution_id INTEGER, + parent_job_id INTEGER, + remote_build_server_id INTEGER, + source_id INTEGER, + jtype VARCHAR(32) NOT NULL, + status VARCHAR(32) NOT NULL DEFAULT 'JUST_CREATED', + start_time DATETIME, + end_time DATETIME, + CONSTRAINT fk_jobs_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ), + CONSTRAINT fk_jobs_users1 FOREIGN KEY ( user_id ) REFERENCES users ( id ), + CONSTRAINT fk_jobs_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ), + CONSTRAINT fk_jobs_distributions1 FOREIGN KEY ( distribution_id ) REFERENCES distributions ( id ), + CONSTRAINT fk_jobs_jobs1 FOREIGN KEY ( parent_job_id ) REFERENCES jobs ( id ), + CONSTRAINT fk_jobs_sources1 FOREIGN KEY ( source_id ) REFERENCES sources ( id ), + CONSTRAINT fk_jobs_remote_build_servers1 FOREIGN KEY ( remote_build_server_id ) REFERENCES remote_build_servers ( id ) )#{post_fix}" + end + + + # save to db + public + def save(db, now) + + prj_id = @project.nil? ? "NULL" : @project.get_project_id() + row=db.select_one("SELECT * FROM jobs WHERE id=#{@id}") + if row.nil? then + start_time = @start_time.strftime("%F %T") + os_id = BuildServer.get_supported_os_id(db, @os) + dist_id = PackageDistribution.get_distribution_id(db, get_distribution_name()) + parent_id = @parent.nil? ? "NULL" : @parent.id + db.do "INSERT INTO jobs(id,project_id,user_id,supported_os_id, distribution_id, parent_job_id,jtype,status,start_time) + VALUES (#{@id},#{prj_id},#{@user_id},#{os_id},#{dist_id},#{parent_id},'#{@type}','#{@status}',#{now})" + else + remote_bs_id = (@type == "BUILD" and not get_remote_server().nil?) ? + get_remote_server().id : "NULL" + if @status == "FINISHED" and not @project.nil? and + (@type == "BUILD" or @type == "REGISTER") then + source_id = @project.get_source_id_from_ver(pkginfo.get_version(),db) + db.do "UPDATE jobs SET source_id=#{source_id} WHERE id=#{@id}" + end + db.do "UPDATE jobs SET status='#{@status}',remote_build_server_id=#{remote_bs_id} WHERE id=#{@id}" + if @status == "FINISHED" or @status == "ERROR" or @status == "CANCELED" then + @end_time = Time.now.strftime("%F %T") + db.do "UPDATE jobs SET end_time=#{now} WHERE id=#{@id}" + end + end + end + + + # + # PROTECTED METHODS + # + + # main module + protected + def job_main + # do nothing + end + + + protected + def kill_sub_process() + if @sub_pid != 0 then + if not @log.nil? then + @log.info("Killing sub process! id = #{@sub_pid}") + end + Utils.kill_process(@sub_pid) + end + end +end diff --git a/src/build_server/CommonProject.rb b/src/build_server/CommonProject.rb new file mode 100644 index 0000000..a2b46ac --- /dev/null +++ b/src/build_server/CommonProject.rb @@ -0,0 +1,355 @@ +=begin + + CommonProject.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" + +class CommonProject + attr_accessor :name, :type, :passwd, :os_list, :dist_name, :path + + # initialize + def initialize( name, type, server, os_list, dist_name="BASE" ) + @prj_id = -1 + @name = name + @type = type + @passwd = "" + @os_list = os_list + @server = server + @dist_name = dist_name + @source_info = {} + @package_info = {} + if @dist_name == "BASE" then + @path = "#{@server.path}/projects/#{@name}" + else + @path = "#{@server.path}/projects/#{@dist_name}/#{@name}" + end + end + + + def ==(y) + @name == y.name and @dist_name = y.dist_name + end + + + def init() + # create project directory if not exist + if not File.exist? @path then FileUtils.mkdir_p @path end + end + + + #return passwd + def is_passwd_set?() + return ( not @passwd.empty? ) + end + + + def passwd_match?(word) + if not is_passwd_set? then return true end + + if word.eql? @passwd then + return true + else + return false + end + end + + + def set_source_info(info) + @source_info = info + end + + + def save_source_info(ver, info) + @source_info[ver] = info + + # save to db + @server.get_db_connection() do |db| + save_source_info_internal(ver, info, db) + end + end + + + def get_source_info(ver) + return @source_info[ver] + end + + + def set_package_info(info) + @package_info = info + end + + + def save_package_info(ver, pkg_name, pkg_os) + if @package_info[ver].nil? then + @package_info[ver] = [] + end + @package_info[ver].push [pkg_name, pkg_os] + + # save to db + @server.get_db_connection() do |db| + save_package_info_internal(ver, pkg_name, pkg_os, db) + end + end + + + # get latest package version + def get_latest_version() + versions = @package_info.keys + if not versions.empty? then + versions.sort! {|x,y| Version.new(x).compare(Version.new(y)) } + return versions[-1] + else + return nil + end + end + + + # get all package version + def get_all_versions() + return @package_info.keys + end + + + def include_package?(pkg_name, ver=nil, os=nil) + # check version first + if not ver.nil? then + ver = get_latest_version() + end + + if ver.nil? or @package_info[ver].nil? then return false end + if not os.nil? and not @os_list.include? os then return false end + + # check name and version + @package_info[ver].each do |pkg| + if pkg_name == pkg[0] and os == pkg[1] then + return true + end + end + + return false + end + + + def set_project_id(id) + @prj_id = id + end + + + def get_project_id() + return @prj_id + end + + def self.create_table(db, inc, post_fix) + db.do "CREATE TABLE projects ( + id INTEGER PRIMARY KEY #{inc}, + distribution_id INTEGER NOT NULL, + user_id INTEGER, + name VARCHAR(32) NOT NULL, + ptype VARCHAR(32) NOT NULL, + password VARCHAR(32), + CONSTRAINT fk_projects_users1 FOREIGN KEY ( user_id ) REFERENCES users ( id ), + CONSTRAINT fk_projects_distributions1 FOREIGN KEY ( distribution_id ) REFERENCES distributions ( id ) )#{post_fix}" + + db.do "CREATE TABLE project_os ( + project_id INTEGER NOT NULL, + supported_os_id INTEGER NOT NULL, + PRIMARY KEY ( project_id,supported_os_id ), + CONSTRAINT fk_projects_has_supported_os_projects FOREIGN KEY ( project_id ) REFERENCES projects ( id ), + CONSTRAINT fk_projects_has_supported_os_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ) )#{post_fix}" + + db.do "CREATE TABLE sources ( + id INTEGER PRIMARY KEY #{inc}, + project_id INTEGER NOT NULL, + pkg_ver VARCHAR(64) NOT NULL, + location VARCHAR(256) NOT NULL, + CONSTRAINT fk_project_sources_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ))#{post_fix}" + + db.do "CREATE TABLE packages ( + id INTEGER PRIMARY KEY #{inc}, + source_id INTEGER NOT NULL, + supported_os_id INTEGER NOT NULL, + pkg_name VARCHAR(64) NOT NULL, + CONSTRAINT fk_project_packages_project_sources1 FOREIGN KEY ( source_id ) REFERENCES sources ( id ), + CONSTRAINT fk_project_packages_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ) )#{post_fix}" + + end + + + protected + def self.load_row(name, dist_name, db) + row = db.select_one("SELECT projects.* FROM projects,distributions WHERE projects.name='#{name}' and + projects.distribution_id=distributions.id and distributions.name='#{dist_name}'") + if row.nil? then return nil end + + # get supported_os + prj_id = row['id'] + os_list = [] + rows = db.select_all("SELECT supported_os.name FROM project_os,supported_os WHERE project_id=#{prj_id} and supported_os.id = project_os.supported_os_id") + rows.each do |r| + os_list.push r['name'] + end + + # get source info/ package info + source_info = {} + package_info = {} + rows=db.select_all("SELECT * FROM sources WHERE project_id=#{prj_id}") + rows.each do |r| + source_info[r['pkg_ver']] = r['location'] + + source_id = r['id'] + rows2=db.select_all("SELECT packages.pkg_name,supported_os.name as os_name + FROM packages,supported_os WHERE source_id=#{source_id} and packages.supported_os_id=supported_os.id") + rows2.each do |r2| + if package_info[r['pkg_ver']].nil? then + package_info[r['pkg_ver']] = [] + end + package_info[r['pkg_ver']].push [r2['pkg_name'], r2['os_name']] + end + end + + return row, os_list, source_info, package_info + end + + + protected + def save_common(db) + if @prj_id == -1 then + row = db.select_one("SELECT * FROM distributions WHERE name='#{@dist_name}'") + dist_id = row['id'] + db.do "INSERT INTO projects (distribution_id,name,ptype,password) + VALUES (#{dist_id},'#{@name}','#{@type}','#{@passwd}')" + case @server.db_dsn + when /^SQLite3:/ then @prj_id = db.select_one("select last_insert_rowid()")[0] + when /^Mysql:/ then @prj_id = db.func(:insert_id) + else @prj_id = db.select_one("select last_insert_rowid()")[0] + end + @os_list.each do |os| + row = db.select_one("SELECT * FROM supported_os WHERE name='#{os}'") + os_id = row['id'] + db.do "INSERT INTO project_os VALUES(#{@prj_id},#{os_id})" + end + + return true + else + row = db.select_one("SELECT * FROM distributions WHERE name='#{@dist_name}'") + dist_id = row['id'] + db.do "UPDATE projects SET ptype='#{@type}',password='#{@passwd}' WHERE name='#{@name}' and distribution_id=#{dist_id})" + db.do "DELETE FROM project_os WHERE project_id=#{@prj_id}" + @os_list.each do |os| + row = db.select_one("SELECT * FROM supported_os WHERE name='#{os}'") + os_id = row['id'] + db.do "INSERT INTO project_os VALUES(#{@prj_id},#{os_id})" + end + + @source_info.each do |src_ver,info| + save_source_info_internal(src_ver, info, db) + end + + @package_info.each do |src_ver,pkg_name_os_pair| + pkg_name_os_pair.each do |pkg_name, pkg_os| + save_package_info_internal(src_ver, pkg_name, pkg_os, db) + end + end + + return false + end + end + + + public + def get_source_id_from_ver( src_ver, db ) + row=db.select_one("SELECT * FROM sources WHERE project_id=#{@prj_id} and pkg_ver='#{src_ver}'") + if row.nil? then + return "NULL" + else + return row['id'] + end + end + + + protected + def save_source_info_internal(src_ver, info, db) + row1=db.select_one("SELECT * FROM sources WHERE project_id=#{@prj_id} and pkg_ver='#{src_ver}'") + if row1.nil? then + db.do "INSERT INTO sources(project_id, pkg_ver,location) + VALUES(#{@prj_id},'#{src_ver}','#{info}')" + end + end + + + protected + def save_package_info_internal(src_ver, pkg_name, pkg_os, db) + row=db.select_one("SELECT * FROM sources WHERE project_id=#{@prj_id} and pkg_ver='#{src_ver}'") + source_id = row['id'] + row = db.select_one("SELECT * FROM supported_os WHERE name='#{pkg_os}'") + os_id = row['id'] + row1=db.select_one("SELECT * FROM packages WHERE source_id=#{source_id} and pkg_name='#{pkg_name}' and supported_os_id=#{os_id}") + if row1.nil? then + db.do "INSERT INTO packages(source_id,supported_os_id,pkg_name) VALUES(#{source_id},#{os_id},'#{pkg_name}')" + end + end + + + # return its prject id and if not exist?, return -1 + protected + def unload_common(db) + row = db.select_one("SELECT * FROM projects WHERE id=#{@prj_id}") + if row.nil? then return -1 end + db.do "DELETE FROM project_os WHERE project_id=#{@prj_id}" + rows=db.select_all("SELECT * FROM sources WHERE project_id=#{@prj_id}") + rows.each do |r| + source_id = r['id'] + db.do "DELETE FROM packages WHERE source_id=#{source_id}" + end + db.do "DELETE FROM sources WHERE project_id=#{@prj_id}" + db.do("DELETE FROM projects WHERE id=#{@prj_id}") + end + + + public + def self.get_project_row(name, dist_name, db) + return db.select_one("SELECT * FROM projects WHERE name='#{name}' AND distribution_id=(SELECT id FROM distributions WHERE name='#{dist_name}')") + end + + public + def self.get_project_from_pkg_name_row(pkg_name, dist_name, db) + return db.select_one("SELECT projects.id,projects.distribution_id,projects.name,projects.ptype,projects.password + FROM distributions,projects,project_bins + WHERE distributions.name='#{dist_name}' and + distributions.id = projects.distribution_id and + projects.id = project_bins.project_id and + project_bins.pkg_name = '#{pkg_name}'") + end + + public + def self.get_all_project_rows(db) + return db.select_all("SELECT projects.name,distributions.name as dist_name,projects.ptype + FROM projects,distributions WHERE projects.distribution_id=distributions.id") + end +end diff --git a/src/build_server/DistributionManager.rb b/src/build_server/DistributionManager.rb new file mode 100644 index 0000000..2550496 --- /dev/null +++ b/src/build_server/DistributionManager.rb @@ -0,0 +1,227 @@ +=begin + + DistributionManager.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +require 'thread' +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server" +require "SocketJobRequestListener.rb" +require "RemoteBuildJob.rb" +require "RegisterPackageJob.rb" +require "packageServer.rb" + +class PackageDistribution + attr_accessor :name, :pkgsvr_url, :pkgsvr_ip, :pkgsvr_port, :status, :description, :id + + def initialize( name, pkgsvr_url, pkgsvr_ip, pkgsvr_port, status ) + @id = -1 + @name = name + @pkgsvr_url = pkgsvr_url + @pkgsvr_ip = pkgsvr_ip + @pkgsvr_port = pkgsvr_port + @status = status + @description = "" + end + + + def self.create_table(db, inc, post_fix) + db.do "CREATE TABLE distributions ( + id INTEGER PRIMARY KEY #{inc}, + name VARCHAR(32) NOT NULL UNIQUE, + pkgsvr_url VARCHAR(256), + pkgsvr_addr VARCHAR(64), + status VARCHAR(32) NOT NULL DEFAULT 'OPEN', + description VARCHAR(256) ) #{post_fix}" + end + + + def self.load(name, db) + row = db.select_one("SELECT * FROM distributions WHERE name='#{name}'") + return ( row.nil? ) ? nil : load_row(row) + end + + + def unload(db) + #TODO remove sync_pkg_server + #TODO remove projects + #TODO remove jobs + db.do("DELETE FROM distributions WHERE name='#{@name}'") + end + + + def self.load_all(db) + rows = db.select_all("SELECT * FROM distributions") + return rows.map{|x| load_row(x)} + end + + + def self.load_first(db) + row = db.select_one("SELECT * FROM distributions ORDER BY id") + return ( row.nil? ) ? nil : load_row(row) + end + + + def self.load_row(row) + pkgsvr_ip = row['pkgsvr_addr'].split(":")[0] + pkgsvr_port = row['pkgsvr_addr'].split(":")[1].to_i + new_obj = new(row['name'], row['pkgsvr_url'], pkgsvr_ip, pkgsvr_port, row['status']) + new_obj.description = row['description'] + new_obj.id = row['id'] + + return new_obj + end + + + def save(db) + dist_addr = @pkgsvr_ip + ":" + @pkgsvr_port.to_s + row = db.select_one("SELECT * FROM distributions WHERE name='#{@name}'") + if row.nil? then + db.do "INSERT INTO distributions(name, pkgsvr_url, pkgsvr_addr, status, description) VALUES ('#{@name}','#{@pkgsvr_url}','#{dist_addr}','#{@status}','#{@description}')" + else + db.do "UPDATE distributions SET pkgsvr_url='#{@pkgsvr_url}', pkgsvr_addr='#{dist_addr}', status='#{@status}', description='#{@description}' WHERE name='#{@name}'" + end + end + + + def self.get_distribution_id(db, dist_name) + row = db.select_one("SELECT * FROM distributions WHERE name='#{dist_name}'") + return ( row.nil? ) ? "NULL" : row['id'] + end +end + + +class DistributionManager + + # initialize + def initialize( server ) + @server = server + end + + + # get default distribution + def get_default_distribution_name() + dist = get_first_distribution() + return ( dist.nil? ) ? nil : dist.name + end + + + def get_default_pkgsvr_url() + dist = get_first_distribution() + return ( dist.nil? ) ? "" : dist.pkgsvr_url + end + + + # get distribution + def get_distribution(name) + # conntect DB + @server.get_db_connection() do |db| + return get_distribution_internal(name, db) + end + return nil + end + + + def get_distribution_internal(name, db) + return PackageDistribution.load(name, db) + end + + + # add + def add_distribution(name, pkgsvr_url, pkgsvr_ip, pkgsvr_port) + @server.get_db_connection() do |db| + if not get_distribution_internal(name, db).nil? then + @server.log.info "The distribution \"#{name}\" already exists on server" + @server.log.error "Adding distribution failed!" + return false + end + new_dist = PackageDistribution.new(name, pkgsvr_url, pkgsvr_ip, pkgsvr_port, "OPEN") + new_dist.save(db) + end + @server.log.info "Added a new distribution \"#{name}\"" + return true + end + + + # remove + def remove_distribution(name) + + result = @server.get_db_connection() do |db| + dist = get_distribution_internal(name, db) + if dist.nil? then + @server.log.error "The distribution \"#{name}\" does not exists on server" + @server.log.error "Removing distribution failed!" + return false + end + dist.unload(db) + end + + @server.log.info "Removed the distribution \"#{name}\"" + return result + end + + + def get_first_distribution() + @server.get_db_connection() do |db| + return PackageDistribution.load_first(db) + end + + return nil + end + + + def get_all_distributions() + @server.get_db_connection() do |db| + return PackageDistribution.load_all(db) + end + + return [] + end + + + def set_distribution_lock(name, value=true) + result = @server.get_db_connection() do |db| + # check already exist + dist = get_distribution_internal(name, db) + if dist.nil? then return false end + + dist.status = (value)? "CLOSE" : "OPEN" + dist.save(db) + end + if result then + if value then + @server.log.info "The distribution \"#{name}\" is locked!" + else + @server.log.info "The distribution \"#{name}\" is unlocked!" + end + end + + return result + end + + #END +end diff --git a/src/build_server/GitBuildJob.rb b/src/build_server/GitBuildJob.rb index d328925..301d810 100644 --- a/src/build_server/GitBuildJob.rb +++ b/src/build_server/GitBuildJob.rb @@ -1,5 +1,5 @@ =begin - + GitBuildJob.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -27,194 +27,286 @@ Contributors: =end require "fileutils" +require "thread" $LOAD_PATH.unshift File.dirname(__FILE__) $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" require "BuildJob.rb" require "utils.rb" + +$git_mutex = Mutex.new + class GitBuildJob < BuildJob - attr_accessor :id, :status, :pkginfo, :pkgsvr_client, :thread, :log, :rev_fail_list, :rev_success_list, :source_path + attr_accessor :git_commit, :git_branch, :git_repos # initialize - def initialize ( repos, commit, os, pkgsvr_url, options, server, parent, outstream, resolve) - super() - @rev_fail_list = [] - @rev_success_list = [] - @id = server.get_new_job_id() - @server = server - @parent = parent - @git_repos = repos - @git_commit = commit - @os = os - @host_os = Utils::HOST_OS - if not pkgsvr_url.nil? and not pkgsvr_url.empty? then - @pkgserver_url = pkgsvr_url - else - local_pkgsvr = @server.local_pkgsvr - @pkgserver_url = local_pkgsvr.location + "/" + local_pkgsvr.get_default_dist_name - end - @options = options - @resolve = resolve - @outstream = outstream - - @status = "JUST_CREATED" - @sub_jobs = [] - @job_root = "#{@server.path}/jobs/#{@id}" - @source_path = @job_root+"/temp" - @pkginfo = nil - @job_working_dir=@job_root+"/works" - - @thread = nil - - # mkdir - FileUtils.rm_rf "#{@server.path}/jobs/#{@id}" - FileUtils.mkdir_p "#{@server.path}/jobs/#{@id}" - - # create logger - @log = JobLog.new(self,"#{@server.path}/jobs/#{@id}/log", outstream ) + def initialize( project, os, server ) + super(project, os, server) + @git_repos = project.repository + @git_branch = project.branch + @git_commit = nil end def terminate() - # report error if @status == "ERROR" then @log.error( "Job is stopped by ERROR" , Log::LV_USER) + @server.cleaner.clean_afterwards(@id) + elsif @status == "CANCELED" then + if not @log.nil? then + @log.error( "Job is CANCELED" , Log::LV_USER) + end + @server.cleaner.clean_afterwards(@id) else - # if succeeded, clean up - FileUtils.rm_rf "#{@source_path}" - FileUtils.rm_rf "#{@job_working_dir}" + @log.info( "Job is FINISHED successfully!" , Log::LV_USER) + + # if succeeded, register source info and copy pkginfo.manifest + @log.info( "Updating the source info for project \"#{@project.name}\"" , Log::LV_USER) + @project.save_source_info( @pkginfo.get_version(), @git_commit) + @project.save_package_info_from_manifest( @pkginfo.get_version(), + "#{@source_path}/package/pkginfo.manifest", @os) + @server.jobmgr.save_job_status(self) + # clean up + @server.cleaner.clean(@id) + end + + # clean up builder directory if exist? + if Builder.exist? "JB#{@id}" then + Builder.remove("JB#{@id}") end - # send mail - if ( not @pkginfo.nil? ) and not ( @pkginfo.packages.nil? ) then + # send mail + if ( @server.send_mail.eql? "YES" ) and ( not @pkginfo.nil? ) and ( not @pkginfo.packages.nil? ) then mail_list = [] contents = [] - done_pkg_list = [] contents.push " " contents.push " Git information : #{@git_commit} " contents.push " " contents.push "%-30s| %10s | %10s" % ["package name", "version", "os"] contents.push "---------------------------------------------------------------" - for pkg in @pkginfo.packages - if not pkg.os.eql? @os then next end - mail_list = mail_list | Mail.parse_email( pkg.maintainer ) + @pkginfo.packages.each do |pkg| + if not pkg.os.eql? @os then next end + mail_list = mail_list | Mail.parse_email( pkg.maintainer ) contents.push("%-30s| %10s | %10s" % [ pkg.package_name, pkg.version, pkg.os] ) end - - if @status == "ERROR" then - subject = "[DIBS] Build fail" + + if @status == "ERROR" then + subject = "[DIBS] Build fail" contents.push " " contents.push "check log file" contents.push "* Log : #{@server.job_log_url}/#{@id}/log" + elsif @status == "CANCELED" then + subject = "[DIBS] Build canceled" else - subject = "[DIBS] Build success" + subject = "[DIBS] Build success" end - #Mail.send_mail(mail_list, subject, contents.join("\n")) - end + Mail.send_mail(mail_list, subject, contents.join("\n")) + end # close logger @log.close + end - # send END signal , if connectionn is valid - if @status != "ERROR" and not @outstream.nil? then - BuildCommServer.send_end(@outstream) - end - # close outstream - if not @outstream.nil? then - BuildCommServer.disconnect( @outstream ) + # verify + def init + # mkdir job root + if not File.exist? @job_root then FileUtils.mkdir_p @job_root end + + # create logger + if @log.nil? then + @log = JobLog.new(self, nil ) end - end + @log.info( "Initializing job...", Log::LV_USER) - # verify - def pre_verify - @log.info( "Verifying job input...", Log::LV_USER) + # if internal job, copy external_pkgs + if @is_internal_job then + @log.info( "Copying external dependent pkgs...", Log::LV_USER) + ext_pkgs_dir = "#{@job_root}/external_pkgs" + + incoming_dir = "#{@server.transport_path}/#{@dock_num}" + if File.exist? incoming_dir then + FileUtils.mv "#{incoming_dir}", "#{ext_pkgs_dir}" + end + + FileUtils.mkdir_p incoming_dir + end - # git clone - if not git_cmd("clone #{@server.git_server_url}#{@git_repos} temp", @job_root) then - @log.error( "Failed on \"git clone #{@server.git_server_url}/#{@git_repos}\"", Log::LV_USER) + # download source code + @git_commit = get_source_code() + if @git_commit.nil? then @status = "ERROR" return false end - # git reset - if not git_cmd("reset --hard #{@git_commit}", @source_path) then - @log.error( "Failed on \"git reset --hard #{@git_commit}\"", Log::LV_USER) + # check pkginfo.manifest + if not File.exist? "#{@source_path}/package/pkginfo.manifest" + @log.error( "package/pkginfo.manifest does not exist", Log::LV_USER) @status = "ERROR" return false end - # check branch name if ALLOWED_GIT_BRANCH is not empty - if not @server.allowed_git_branch.empty? then - is_correct_branch = false - - # origin/{branch_name} - if @git_commit == "origin/#{@server.allowed_git_branch}" then - is_correct_branch = true - else - # get commit id - commit_id = "" - result_line = git_cmd_return("log -1",@source_path) - if result_line != nil then - result_line.each do |l| - if l.start_with?("commit ") then - commit_id = l.split(" ")[1].strip - end - end - end - - # check branch - if not commit_id.empty? and commit_id.length == 40 then - result_line = git_cmd_return("branch --contains=#{commit_id} -r", @source_path) - result_line.each do |l| - if l.include? "origin/#{@server.allowed_git_branch}" then - is_correct_branch = true - end - end - end + # set up pkg info + begin + @pkginfo = PackageManifest.new("#{@source_path}/package/pkginfo.manifest") + rescue => e + @log.error( e.message, Log::LV_USER) + return false + end + + # set up pkgsvr_client + @pkgsvr_client = Client.new(@pkgsvr_url, @job_working_dir, @log) + + # checking version if not reverse-build job or not internal-job + if not @is_rev_build_check_job and not @is_internal_job then + + #check change log + change_log = {} + begin + change_log = Parser.read_changelog "#{@source_path}/package/changelog" if File.exist? "#{@source_path}/package/changelog" + rescue => e + @log.error( e.message, Log::LV_USER) + return false end - if not is_correct_branch then - @log.error( "Wrong branch is used! Check your commit-id again", Log::LV_USER) + if not change_log.empty? and @pkginfo.packages[0].change_log.empty? then + @pkginfo.packages.each {|pkg| pkg.change_log = change_log} + end + + if @server.changelog_check and not @pkginfo.packages[0].does_change_exist? then + @log.error( "change log not found", Log::LV_USER ) + return false + end + + # check availabiltiy + if not @server.check_job_availability( self ) then + @log.error( "No servers that are able to build your packages.", Log::LV_USER) + @log.error( "Host-OS (#{@os}) is not supported in build server.", Log::LV_USER) + @status = "ERROR" + @server.log.info "Adding the job \"#{@id}\" is canceled" + return false + end + + if not check_package_version(@git_commit) then @status = "ERROR" return false end end - - # check pkginfo.manifest - if not File.exist? "#{@source_path}/package/pkginfo.manifest" - @log.error( "package/pkginfo.manifest doest not exist", Log::LV_USER) - @status = "ERROR" - return false + return true + end + + + # + # PROTECTED/PRIVATE METHODS + # + + protected + def get_source_code() + $git_mutex.synchronize do + get_source_code_internal() end + end - # set up pkg info - @pkginfo = PackageManifest.new("#{@source_path}/package/pkginfo.manifest") - # set up pkgsvr_client - @pkgsvr_client = Client.new(@pkgserver_url, @job_working_dir, @log) - @pkgsvr_client.update + protected + def get_source_code_internal() + # check git directory + git_path = "#{@project.path}/cache/git" + cache_path = "#{@project.path}/cache" + if not File.exist? cache_path then + FileUtils.mkdir_p cache_path + end - return true + # verify git & check branch name + if File.exist? git_path then + std_out_lines = git_cmd_return( "branch", git_path) + if std_out_lines.nil? then + @log.warn( "Git cache is corrupted! : #{@project.name}", Log::LV_USER) + FileUtils.rm_rf git_path + else + branch_list = std_out_lines.select{|x| x.start_with?("*")} + if branch_list.count == 0 then + @log.warn( "Git cache is corrupted! : #{@project.name}", Log::LV_USER) + FileUtils.rm_rf git_path + else + current_branch = branch_list[0].split(" ")[1].strip + if current_branch != @git_branch then + @log.warn( "Branch name is changed.", Log::LV_USER) + FileUtils.rm_rf git_path + end + end + end + end + + # git pull operation + if File.exist? git_path and not git_cmd("pull", git_path,@log) then + @log.warn( "Failed on \"git pull\"", Log::LV_USER) + FileUtils.rm_rf git_path + end + + # if no git, clone it + if not File.exist? git_path then + # if "git pull" failed, try to "git clone" + if not git_cmd("clone #{@git_repos} git", cache_path, @log) then + @log.error( "Failed on \"git clone #{@git_repos}\"", Log::LV_USER) + return nil + end + # git checkout + if not git_cmd("checkout #{@git_branch}", git_path, @log) then + @log.error( "Failed on \"git checkout #{@git_branch}\"", Log::LV_USER) + return nil + end + end + + if @git_commit.nil? then + # get git commit-id + commit_id = "" + result_line = git_cmd_return("log -1", git_path) + if result_line != nil then + result_line.each do |l| + if l.start_with?("commit ") then + commit_id = l.split(" ")[1].strip + end + end + end + + @git_commit = commit_id + else + # git reset + if not git_cmd("reset --hard #{@git_commit}", git_path, @log) then + @log.error( "Failed on \"git reset --hard #{@git_commit}\"", Log::LV_USER) + return nil + end + end + + # copy to source path + Utils.execute_shell_return( "cp -r #{git_path} #{@source_path}" ) + + return @git_commit end - def git_cmd(cmd, working_dir) - build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}" - ret = Utils.execute_shell_with_log(build_command,@log) - - return ret + protected + def git_cmd(cmd, working_dir, log) + build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}" + + pid, status = execute_command( build_command ) + if not status.nil? and status.exitstatus != 0 then + return false + else + return true + end end - def git_cmd_return(cmd, working_dir) - build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}" + protected + def git_cmd_return(cmd, working_dir) + build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}" ret = Utils.execute_shell_return(build_command) - + return ret end - end diff --git a/src/build_server/GitBuildProject.rb b/src/build_server/GitBuildProject.rb new file mode 100644 index 0000000..589651b --- /dev/null +++ b/src/build_server/GitBuildProject.rb @@ -0,0 +1,154 @@ +=begin + + GitProject.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +require 'dbi' +$LOAD_PATH.unshift File.dirname(__FILE__) +require "CommonProject.rb" +require "GitBuildJob.rb" +require "Version.rb" +require "PackageManifest.rb" + +# mutax for git operation + + +class GitBuildProject < CommonProject + attr_accessor :repository, :branch + + # initialize + def initialize( name, server, os_list, dist_name, repos = nil, branch = nil ) + super(name, "GIT", server, os_list, dist_name) + @repository = repos + @branch = branch + end + + + # get commid-id of specified package version + def get_commit_id( version ) + return get_source_info( version ) + end + + + # create new job + # if this project cannot support os, return nil + def create_new_job( os ) + if @os_list.include? os then + return GitBuildJob.new( self, os, @server ) + else + return nil + end + end + + + # create new job + def create_new_job_from_version( os, version=nil ) + new_job=create_new_job( os ) + + # set commit id + if version.nil? then + version = get_latest_version() + end + + commit = get_commit_id( version ) + if not commit.nil? then + new_job.git_commit = commit + end + + return new_job + end + + + # save package info + def save_package_info_from_manifest(version, file_path, os) + begin + pkginfo =PackageManifest.new(file_path) + rescue => e + @server.log.error e.message + return + end + + pkginfo.get_target_packages(os).each do |pkg| + save_package_info(pkg.version, pkg.package_name, os) + end + end + + + def self.create_table(db, post_fix) + db.do "CREATE TABLE project_gits ( + project_id INTEGER NOT NULL, + git_repos VARCHAR(128) NOT NULL, + git_branch VARCHAR(32) NOT NULL, + PRIMARY KEY ( project_id ), + CONSTRAINT fk_project_gits_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ) )#{post_fix}" + end + + + def self.load(name, dist_name, server, db) + row, prj_os_list, source_info, package_info = load_row(name, dist_name, db) + if row.nil? then return nil end + + prj_id = row['id'] + prj_name = row['name'] + prj_passwd = row['password'] + + new_project = GitBuildProject.new(prj_name, server, prj_os_list, dist_name) + if not prj_passwd.empty? then new_project.passwd = prj_passwd end + new_project.set_project_id( prj_id ) + new_project.set_source_info( source_info ) + new_project.set_package_info( package_info ) + + row=db.select_one("SELECT * FROM project_gits WHERE project_id=#{prj_id}") + if row.nil? then return nil end + new_project.repository=row['git_repos'] + new_project.branch=row['git_branch'] + + return new_project + end + + + def save(db) + is_new = save_common(db) + init() + + if is_new then + db.do "INSERT INTO project_gits VALUES (#{@prj_id},'#{@repository}','#{@branch}')" + db.do "INSERT INTO group_project_accesses + VALUES ( (SELECT groups.id FROM groups WHERE groups.name = 'admin'),'#{@prj_id}','TRUE')" + else + db.do "UPDATE project_gits SET git_repos='#{@repository}',git_branch='#{@branch}' WHERE project_id=#{@prj_id})" + end + end + + + def unload(db) + unload_common(db) + if @prj_id != -1 then + db.do "DELETE FROM project_gits WHERE project_id=#{@prj_id}" + end + end +end diff --git a/src/build_server/JobClean.rb b/src/build_server/JobClean.rb new file mode 100644 index 0000000..54d8597 --- /dev/null +++ b/src/build_server/JobClean.rb @@ -0,0 +1,199 @@ +=begin + + JobClean.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "fileutils" +require "thread" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "Action.rb" +require "ScheduledActionHandler.rb" + +$access_listfile = Mutex.new + +class JobCleanAction < Action + + def initialize( time, job_path, list_file, server ) + super(time,0) + + @job_path = job_path + @job_id = @job_path.split("/")[-1] + @list_file = list_file + @server = server + end + + + def init + $access_listfile.synchronize do + File.open(@list_file, "a") do |f| + f.puts "#{@job_id},#{time.year},#{time.month},#{time.day},#{time.hour},#{time.min},#{time.sec}" + end + end + end + + + def execute + # Start to clean job + @server.log.info "Executing clean action for the job #{@job_id}" + begin + execute_internal() + rescue => e + @server.log.error e.message + @server.log.error e.backtrace.inspect + end + end + + + private + def execute_internal() + # remove directories + if File.exist? "#{@job_path}/buildroot" then + FileUtils.rm_rf "#{@job_path}/buildroot" + end + if File.exist? "#{@job_path}/temp" then + FileUtils.rm_rf "#{@job_path}/temp" + end + if File.exist? "#{@job_path}/external_pkgs" then + FileUtils.rm_rf "#{@job_path}/external_pkgs" + end + + # remove line for the job + $access_listfile.synchronize do + lines = [] + # get all lines + if File.exist? @list_file then + File.open(@list_file,"r") do |f| + f.each_line do |l| + lines.push l + end + end + end + + # write the line except my job_id + File.open(@list_file,"w") do |f| + lines.each do |l| + if l.split(",")[0].eql? @job_id then next end + f.puts l + end + end + end + end +end + + +class JobCleaner + attr_accessor :quit + + # init + def initialize( server ) + @server = server + @handler = ScheduledActionHandler.new + @list_file = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/clean" + end + + + # start thread + def start() + + list_file2 = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/clean_backup" + jobs_path = "#{@server.path}/jobs" + if not File.exist? jobs_path then + FileUtils.mkdir_p jobs_path + end + + # read clean list + clean_list = [] + if File.exist? @list_file then + FileUtils.mv(@list_file,list_file2) + File.open(list_file2, "r") do |f| + f.each_line do |l| + id = l.split(",")[0] + year = l.split(",")[1] + month = l.split(",")[2] + day = l.split(",")[3] + hour = l.split(",")[4] + min = l.split(",")[5] + sec = l.split(",")[6] + + # create job and register + job_path = "#{jobs_path}/#{id}" + time = Time.mktime(year.to_i, month.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i) + @server.log.info "Registered clean-action for the job in list : #{id}" + @handler.register(JobCleanAction.new(time,job_path,@list_file, @server)) + + # add clean list + clean_list.push id + end + end + end + + + # scan all jobs + Dir.new(jobs_path).entries.each do |id| + # skip . or .. + if id.eql? "." or id.eql? ".." then next end + + # remove directory if jobs directory is created too long ago + job_path = "#{jobs_path}/#{id}" + dir_keep_time = 86400 < @server.keep_time ? @server.keep_time : 86400 + if File.ctime(job_path) + dir_keep_time < Time.now then + FileUtils.rm_rf job_path + @server.log.info "Removed the job directory: #{id}" + next + end + + if not clean_list.include? id then + time = Time.now + @server.log.info "Registered clean-action for old job : #{id}" + @handler.register(JobCleanAction.new(time,job_path,@list_file, @server)) + end + end + + # start handler + @handler.start + end + + + # clean after some time + def clean_afterwards(job_id) + time = Time.now + @server.keep_time + job_path = "#{@server.path}/jobs/#{job_id}" + @handler.register(JobCleanAction.new(time, job_path, @list_file, @server)) + + @server.log.info "Registered delayed clean-action for the job #{job_id}" + end + + + # clean directly + def clean(job_id) + time = Time.now + job_path = "#{@server.path}/jobs/#{job_id}" + @handler.register(JobCleanAction.new(time, job_path, @list_file, @server)) + + @server.log.info "Registered clean-action for the job #{job_id}" + end +end diff --git a/src/build_server/JobLog.rb b/src/build_server/JobLog.rb index c46db48..def8056 100644 --- a/src/build_server/JobLog.rb +++ b/src/build_server/JobLog.rb @@ -1,6 +1,6 @@ =begin - - JobLog.rb + + JobLog.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -34,37 +34,80 @@ require "BuildComm.rb" class JobLog < Log - def initialize(job, path, stream_out) - super(path) + def initialize(job, stream_out, verbose = false) + log_level = (verbose) ? Log::LV_NORMAL : Log::LV_USER + if job.nil? then + super(nil) + else + if not File.exist? "#{job.server.path}/jobs/#{job.id}" then + FileUtils.mkdir_p "#{job.server.path}/jobs/#{job.id}" + end + super("#{job.server.path}/jobs/#{job.id}/log",log_level) + end @parent_job=job @second_out = stream_out end + def set_second_out( out ) + @second_out = out + end + + + def close + # close communication + if not @second_out.nil? then + begin + if not @second_out.closed? then + BuildCommServer.send_end(@second_out) + end + rescue + end + BuildCommServer.disconnect(@second_out) + end + + @second_out = nil + end + + + def is_connected? + if @second_out.nil? or @second_out.closed? then + return false + else + return true + end + end + + + def has_second_out? + if @second_out.nil? then + return false + else + return true + end + end + + protected # overide def output_extra(msg) - begin + begin if not @second_out.nil? then BuildCommServer.send( @second_out, msg ) end rescue - @parent_job.status="ERROR" - close() - error "Connection closed by remote client" + # close second_out + @second_out.close + @second_out = nil - # terminate job - @parent_job.terminate + error "Connection closed by remote client" - # exit thread if independent worker thread - if @parent_job.thread == Thread.current then - error "Thread wiil be terminated" - @parent_job.thread=nil - Thread.exit + # cancel parent job + if not @parent_job.nil? and @parent_job.cancel_state == "NONE" then + @parent_job.cancel_state = "INIT" end end - end - + end end diff --git a/src/build_server/JobManager.rb b/src/build_server/JobManager.rb new file mode 100644 index 0000000..dc6dbae --- /dev/null +++ b/src/build_server/JobManager.rb @@ -0,0 +1,589 @@ +=begin + + JobManager.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +require 'thread' +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server" +require "SocketJobRequestListener.rb" +require "RemoteBuildJob.rb" +require "RegisterPackageJob.rb" +require "packageServer.rb" + + +class JobManager + attr_accessor :jobs, :internal_jobs, :reverse_build_jobs + attr_accessor :internal_job_schedule + + # initialize + def initialize( parent ) + @server = parent + @jobs = [] + @internal_jobs = [] + @reverse_build_jobs = [] + @new_job_index = 0 + @internal_job_schedule = Mutex.new + @latest_job_touch = Mutex.new + end + + def cancel_broken_status + @server.get_db_connection() do |db| + db.do "UPDATE jobs SET status = 'CANCELED' WHERE status != 'FINISHED' and status != 'ERROR' and status != 'CANCELED'" + end + end + + def max_working_jobs + result = nil + @server.get_db_connection() do |db| + result = db.select_one("SELECT value FROM server_configs WHERE property = 'max_working_jobs'")[0] + end + return (result.nil?) ? 2 : result.to_i + end + + def max_working_jobs=(job_cnt) + @server.get_db_connection() do |db| + db.do "UPDATE server_configs SET value = '#{job_cnt}' WHERE property = 'max_working_jobs'" + end + end + + # initialize + def init() + # load latest job idx if exist + file_path = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/latest_job" + if File.exist? file_path then + latest_idx = -1 + File.open( file_path, "r" ) do |f| + f.each_line do |l| + latest_idx = l.strip.to_i + break + end + end + if latest_idx < 0 then latest_idx = -1 end + @new_job_index = latest_idx + 1 + else + @new_job_index = 0 + end + end + + + # get new id + def get_new_job_id + new_idx = 0 + @latest_job_touch.synchronize do + new_idx = @new_job_index + + file_path = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/latest_job" + File.open( file_path, "w" ) do |f| + f.puts "#{@new_job_index}" + end + + @new_job_index += 1 + end + + return new_idx + end + + def is_user_accessable(job,user_id) + if job.type == "MULTIBUILD" then + job.get_sub_jobs().each do |subjob| + if is_user_accessable(subjob,user_id) then + return true + end + end + else + result = nil + @server.get_db_connection() do |db| + result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses + WHERE user_groups.group_id = group_project_accesses.group_id and + group_project_accesses.project_id = #{job.get_project.get_project_id} and + user_groups.user_id = #{user_id}" + end + return (not result.nil?) + end + return false + end + + def create_new_register_job( file_path, dist_name ) + return RegisterPackageJob.new( file_path, nil, @server, nil, dist_name ) + end + + def set_remote(job, rserver) + job.set_remote_job(rserver) + @server.get_db_connection() do |db| + db.do "UPDATE jobs SET remote_build_server_id = '#{rserver.id}' WHERE id = '#{job.id}'" + end + end + + # add a normal job + def add_job ( new_job ) + @server.log.info "Added new job \"#{new_job.id}\"" + save_job_status(new_job) + @jobs.push( new_job ) + end + + # add internal job for multi-build job + def add_internal_job( new_job ) + @server.log.info "Added new job \"#{new_job.id}\"" + save_job_status(new_job) + @internal_jobs.push( new_job ) + end + + # add reverse build chek job + def add_reverse_build_job( new_job ) + @server.log.info "Added new job \"#{new_job.id}\"" + save_job_status(new_job) + @reverse_build_jobs.push( new_job ) + end + + # stop internal job selection + def stop_internal_job_schedule() + @internal_job_schedule.lock + end + + + # start internal job selection + def resume_internal_job_schedule() + @internal_job_schedule.unlock + end + + # intialize normal job + def initialize_job ( job ) + job.status = "INITIALIZING" + job.thread = Thread.new do + save_job_status(job) + begin + # init + if not job.init or job.status == "ERROR" then + if job.cancel_state == "NONE" then job.status = "ERROR" end + @server.log.info "Adding the job \"#{job.id}\" is canceled" + job.terminate() + save_job_status(job) + Thread.current.exit + end + if job.status != "FINISHED" then + job.status = "WAITING" + save_job_status(job) + end + @server.log.info "Checking the job \"#{job.id}\" was finished!" + rescue => e + @server.log.error e.message + @server.log.error e.backtrace.inspect + ensure + job.thread = nil + end + end + @server.log.info "Job \"#{job.id}\" entered INITIALIZING status" + end + + + #execute + def execute(job) + job.status = "WORKING" + save_job_status(job) + + # start build + job.execute + @server.log.info "Moved the job \"#{job.id}\" to working job list" + end + + + # execute remote + def execute_remote(job, rserver) + + # start build + set_remote(job, rserver) + if job.execute() then + # status change & job control + job.status = "REMOTE_WORKING" + save_job_status(job) + @server.log.info "Moved the job \"#{job.id}\" to remote job list" + else + @server.log.info "Moving the job \"#{job.id}\" to remote failed" + end + end + + def cancel_job( job) + job.cancel_state = "WORKING" + @server.log.info "Creating thread for canceling the job \"#{job.id}\"" + Thread.new do + begin + #terminate job thread + if not job.thread.nil? then + job.thread.terminate + job.thread = nil + end + + # job cacncel + job.cancel + + # cancel finished + job.status = "CANCELED" + save_job_status(job) + + # call terminate process for job + job.terminate + rescue => e + @server.log.error e.message + @server.log.error e.backtrace.inspect + end + end + end + + # handle + def handle() + # for cancel jobs + (@jobs + @internal_jobs + @reverse_build_jobs).select {|j| j.cancel_state == "INIT" }.each do |job| + cancel_job( job ) + end + + # for reverse build jobs + job_list = @reverse_build_jobs + job_list.each do |job| + # if "ERROR", "FINISHED", "CANCELED" remove it from list + if job.status == "ERROR" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is stopped by ERROR" + @reverse_build_jobs.delete job + elsif job.status == "FINISHED" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is removed by FINISH status" + @reverse_build_jobs.delete job + elsif job.status == "CANCELED" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is removed by CANCELED status" + @reverse_build_jobs.delete job + end + + # if "JUST_CREATED", initialize it + if job.status == "JUST_CREATED" then + initialize_job( job ) + end + end + + # for internal jobs + job_list = @internal_jobs + job_list.each do |job| + # if "ERROR", "FINISHED", "CANCELED" remove it from list + if job.status == "ERROR" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is stopped by ERROR" + @internal_jobs.delete job + elsif job.status == "FINISHED" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is removed by FINISH status" + @internal_jobs.delete job + elsif job.status == "CANCELED" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is removed by CANCELED status" + @internal_jobs.delete job + end + + # if "JUST_CREATED", initialize it + if job.status == "JUST_CREATED" then + initialize_job( job ) + end + end + + # for normal job + job_list = @jobs + job_list.each do |job| + # if "ERROR", "FINISHED", "CANCELED" remove it from list + if job.status == "ERROR" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is stopped by ERROR" + @jobs.delete job + elsif job.status == "FINISHED" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is removed by FINISH status" + @jobs.delete job + elsif job.status == "CANCELED" + save_job_status(job) + @server.log.info "Job \"#{job.id}\" is removed by CANCELED status" + @jobs.delete job + end + + # if "JUST_CREATED", initialize it + if job.status == "JUST_CREATED" then + initialize_job( job ) + end + + # check the connection if job is not asynchronous job + if ( job.status == "WAITING" or job.status == "REMOTE_WORKING" or job.status == "PENDING") and + not job.is_asynchronous_job? and + not job.is_connected? then + + job.status = "ERROR" + save_job_status(job) + @jobs.delete( job ) + @server.log.info "Job \"#{job.id}\" is disconnected by user. Removed!" + end + end + + # reverse build job -> internal job -> normal job + job = get_available_job + + # available job not exist?, continue + if not job.nil? then + # oherwise, check remote server + rserver = @server.get_available_server( job ) + if rserver != nil and rserver == @server then + execute(job) + elsif rserver != nil then + execute_remote(job, rserver) + else + #puts "No available server" + end + end + + end + + + # select the job whith no build-dependency problem + def get_available_job + # select reverse build job with round-robin method + selected_job = nil + @reverse_build_jobs.each do |job| + if job.status == "WAITING" then + selected_job = job + break + end + end + # rotate array + if @reverse_build_jobs.count > 0 then + @reverse_build_jobs.push @reverse_build_jobs.shift + end + if not selected_job.nil? then return selected_job end + + # if no reverse build job exist! + @internal_job_schedule.synchronize do + # internal job first + ret = nil + if @internal_jobs.count > 0 then + ret = get_available_job_in_list(@internal_jobs, true) + end + + # not found, select normal job + if ret.nil? then + ret = get_available_job_in_list(@jobs, false) + end + + return ret + end + end + + + # return "max_working_jobs_cnt - current_working_jobs_cnt" + def get_number_of_empty_room + working_cnt = 0 + parent_list = [] + (@jobs + @internal_jobs + @reverse_build_jobs).each do |job| + if job.status == "WORKING" then + working_cnt = working_cnt + 1 + end + + # must exclude parent job + if not job.get_parent_job().nil? then + parent_list.push job.get_parent_job() + end + end + + parent_list.uniq! + + return max_working_jobs - working_cnt + parent_list.count + end + + + # check there are working jobs + def has_working_jobs + (@jobs + @internal_jobs + @reverse_build_jobs).each do |job| + if job.status == "WORKING" then + return true + end + end + + return false + end + + + # check there are waiting jobs + def has_waiting_jobs + (@jobs + @internal_jobs + @reverse_build_jobs).each do |job| + if job.status == "WAITING" then + return true + end + end + + return false + end + + + def get_working_jobs + result = [] + (@jobs + @internal_jobs + @reverse_build_jobs).each do |job| + if job.status == "WORKING" then + result.push job + end + end + + return result + end + + + def get_waiting_jobs + result = [] + (@jobs + @internal_jobs + @reverse_build_jobs).each do |job| + if job.status == "WAITING" then + result.push job + end + end + + return result + end + + + def get_remote_jobs + result = [] + (@jobs + @internal_jobs + @reverse_build_jobs).each do |job| + if job.status == "REMOTE_WORKING" then + result.push job + end + end + + return result + end + + + def get_pending_jobs + result = [] + @jobs.each do |job| + if job.status == "PENDING" then + result.push job + end + end + + return result + end + + def save_job_status(job) + now = @server.db_now + result = @server.get_db_connection() do |db| + job.save(db, now) + end + + return result + end + + + protected + # select the job whith no build-dependency problem + # if "check_dep_wait" is true, it will check the build dependency + # among items of "WAIT" status in list + def get_available_job_in_list( jobs, check_dep_wait=false ) + + # gather all working jobs and full-build jobs + check_dep_jobs = [] + jobs.each do |job| + if job.cancel_state != "NONE" then next end + + if job.status == "WORKING" or job.status == "REMOTE_WORKING" or job.status == "PENDING" then + check_dep_jobs.push job + elsif ( check_dep_wait and job.status == "WAITING") then + check_dep_jobs.push job + end + end + + # get candidates for waiting jobs + candidate_jobs = [] + jobs.each do |job| + if job.cancel_state != "NONE" then next end + if job.status != "WAITING" then next end + + # check build dependency against working job + pre_jobs = [] + check_dep_jobs.each do |cjob| + if job == cjob then next end + # In case that "WORKING/REMOTE_WORKING" job has build dependency on me + if (cjob.status == "WORKING" or cjob.status == "REMOTE_WORKING" ) and + (job.has_build_dependency?( cjob ) or job.is_compatible_with?( cjob)) then + pre_jobs.push cjob + # In case that "PENDING" job is depends on me (not depended ) + elsif cjob.status == "PENDING" and (not job.does_depend_on? cjob) and + (job.has_build_dependency?( cjob ) or job.is_compatible_with?( cjob)) then + pre_jobs.push cjob + elsif check_dep_wait and cjob.status == "WAITING" and + (job.does_depend_on? cjob or + (job.id > cjob.id and job.is_compatible_with? cjob) ) then + pre_jobs.push cjob + end + end + + # check pre-requisite jobs are changed, notify to user + is_changed = false + if pre_jobs.count != job.pre_jobs.count then + is_changed=true + else + pre_jobs.each do |pjob| + if not job.pre_jobs.include? pjob then + is_changed = true + break + end + end + end + if pre_jobs.count > 0 and is_changed then + job.log.info( "Waiting for finishing following jobs:", Log::LV_USER) + pre_jobs.each do |bjob| + if bjob.type == "BUILD" then + job.log.info( " * #{bjob.id} #{bjob.pkginfo.packages[0].source}", Log::LV_USER) + elsif bjob.type == "MULTIBUILD" then + job.log.info( " * #{bjob.id} (Multi Build Job)", Log::LV_USER) + end + end + end + job.pre_jobs = pre_jobs + + # no pre-requisite jobs, return its job + if job.pre_jobs.count == 0 then + candidate_jobs.push job + end + end + + # select a job by priority + if candidate_jobs.count == 0 then return nil end + max_priority = -1 + max_priority_job = nil + candidate_jobs.each do |job| + if max_priority < job.priority then + max_priority = job.priority + max_priority_job = job + end + end + + return max_priority_job + end + +end diff --git a/src/build_server/MultiBuildJob.rb b/src/build_server/MultiBuildJob.rb new file mode 100644 index 0000000..5e5d98e --- /dev/null +++ b/src/build_server/MultiBuildJob.rb @@ -0,0 +1,456 @@ +=begin + + MultiBuildJob.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "fileutils" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/builder" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server" +require "client.rb" +require "PackageManifest.rb" +require "Version.rb" +require "Builder.rb" +require "RemoteBuilder.rb" +require "JobLog.rb" +require "mail.rb" +require "CommonJob.rb" + +class MultiBuildJob < CommonJob + + attr_accessor :source_path, :cancel_state + attr_accessor :pkgsvr_client, :thread + + # initialize + def initialize (server) + super(server) + @log = nil + @type = "MULTIBUILD" + + @host_os = Utils::HOST_OS + @pkgsvr_url = nil + @pkgsvr_ip = nil + @pkgsvr_port = nil + @job_root = "#{@server.path}/jobs/#{@id}" + @source_path = @job_root+"/temp" + @job_working_dir=@job_root+"/works" + @buildroot_dir = "#{@job_root}/buildroot" + @cancel_state = "NONE" + + end + + + def get_distribution_name() + return @sub_jobs[0].get_project().dist_name + end + + + def get_buildroot() + return @buildroot_dir + end + + + def is_rev_build_check_job() + return false + end + + def set_no_reverse() + @sub_jobs.each do |sub| + sub.no_reverse = true + end + end + + # cnacel + def cancel() + @sub_jobs.select{|x| x.cancel_state == "NONE"}.each do |sub| + sub.cancel_state = "INIT" + end + if not @log.nil? then + @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER) + end + end + + # + def init + # mkdir + if not File.exist? @job_root then + FileUtils.mkdir_p @job_root + end + + # create logger + if @log.nil? then + @log = JobLog.new(self, nil ) + end + + @log.info( "Initializing job...", Log::LV_USER) + + # create source path + if not File.exist? @source_path then + FileUtils.mkdir_p @source_path + end + + # initialize all sub jobs and add them to "internal_jobs" + @sub_jobs.each do |job| + # initialize job + if not job.init or job.status == "ERROR" then + job.status = "ERROR" + @log.info( "Failed to initialize sub-job \"#{job.get_project().name}\" for #{job.os}. (#{job.id})", Log::LV_USER) + job.terminate() + end + + if job.status != "ERROR" then + job.status = "WAITING" + else + job.status = "ERROR" + @status = "ERROR" + end + end + if @status == "ERROR" then + return false + end + + + # set up pkgsvr_client + first_project = @sub_jobs[0].get_project() + @pkgsvr_url = @server.distmgr.get_distribution(first_project.dist_name).pkgsvr_url + @pkgsvr_ip = @server.distmgr.get_distribution(first_project.dist_name).pkgsvr_ip + @pkgsvr_port = @server.distmgr.get_distribution(first_project.dist_name).pkgsvr_port + @pkgsvr_client = Client.new(@pkgsvr_url, @job_working_dir, @log) + + return true + end + + + #terminate + def terminate() + + # report error + if @status == "ERROR" then + # register delayed clean action for sub jobs + @sub_jobs.each do |job| + @server.cleaner.clean_afterwards(job.id) + end + + # register delayed clean action for me + @log.error( "Job is stopped by ERROR" , Log::LV_USER) + @server.cleaner.clean_afterwards(@id) + + elsif @status == "CANCELED" then + # register delayed clean action for sub jobs + @sub_jobs.each do |job| + @server.cleaner.clean_afterwards(job.id) + end + + # register delayed clean action for me + @log.error( "Job is stopped by CANCEL" , Log::LV_USER) + @server.cleaner.clean_afterwards(@id) + + else + # terminate all sub jobs + @sub_jobs.each do |job| + if not job.log.nil? then job.terminate() end + end + + # register direct clean action for me + @server.cleaner.clean(@id) + end + + # close logger + @log.close + end + + + # check building is possible + def can_be_built_on?(host_os) + return true + end + + + def get_packages() + packages = [] + @sub_jobs.each do |job| + packages = packages + job.get_packages() + end + packages.uniq! + + return packages + end + + + def get_build_dependencies(target_os) + deps = [] + @sub_jobs.each do |job| + deps = deps + job.get_build_dependencies(target_os) + end + deps.uniq! + + return deps + end + + + def get_source_dependencies(target_os, host_os) + deps = [] + @sub_jobs.each do |job| + deps = deps + job.get_source_dependencies(target_os,host_os) + end + deps.uniq! + + return deps + end + + + def is_compatible_with?(o) + return false + end + + def has_build_dependency?(other_job) + + if has_same_packages?(other_job) or + does_depend_on?(other_job) or + does_depended_by?(other_job) then + + return true + else + return false + end + end + + + def has_same_packages?( wjob ) + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + # same package must have same os + if not @os.eql? wjob.os then + return false + end + + # check package name + get_packages.each do |pkg| + wjob.get_packages().each do |wpkg| + if pkg.package_name == wpkg.package_name then + #puts "Removed from candiated... A == B" + return true + end + end + end + + return false + end + + + def does_depend_on?( wjob ) + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + # compare build dependency + get_build_dependencies(@os).each do |dep| + wjob.get_packages().each do |wpkg| + # dep packages of my job must have same name and target os + # with packages in working job + if dep.package_name == wpkg.package_name and + dep.target_os_list.include? wjob.os then + #puts "Removed from candiated... A -> B" + return true + end + end + end + + return false + end + + + def does_depended_by?( wjob ) + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + get_packages().each do |pkg| + wjob.get_build_dependencies(wjob.os).each do |dep| + # dep package of working job must have same name and target os + # with packages in my job + if dep.package_name == pkg.package_name and + dep.target_os_list.include? @os then + #puts "Checking... A <- B" + return true + end + end + end + return false + end + + + def is_connected? + return true + end + + + # return the job is asyncronous job + def is_asynchronous_job? + return false + end + + + def get_log_url() + # only when server support log url + if @server.job_log_url.empty? then + return "","" + end + + return "#{@server.job_log_url}/#{@id}/log","" + end + + # + # PROTECTED/PRIVATE METHODS + # + + + # main module + protected + def job_main() + @log.info( "Invoking a thread for MULTI-BUILD Job #{@id}", Log::LV_USER) + if @status == "ERROR" then return end + @log.info( "New Job #{@id} is started", Log::LV_USER) + + # initialize status map + job_status_map = {} + @sub_jobs.each do |job| + job_status_map[job.id] = job.status + end + + # add to internal job + @server.jobmgr.internal_job_schedule.synchronize do + @sub_jobs.each do |job| + # init finished, add internal_jobs + @server.jobmgr.add_internal_job(job) + @log.info( "Added new job \"#{job.get_project().name}\" for #{job.os}! (#{job.id})", + Log::LV_USER) + if not @server.job_log_url.empty? then + @log.info( " * Log URL : #{@server.job_log_url}/#{job.id}/log", Log::LV_USER) + end + end + end + + # show job status changes + all_jobs_finished = false + stop_status = "FINISHED" + while not all_jobs_finished + all_jobs_finished = true + @sub_jobs.each do |job| + # check status chanaged, if then print + if job_status_map[ job.id ] != job.status then + @log.info(" * Sub-Job \"#{job.get_project().name}(#{job.os})\" has entered \"#{job.status}\" state. (#{job.id})", Log::LV_USER) + job_status_map[ job.id ] = job.status + end + # check all jobs are finished + if job.status != "ERROR" and job.status != "FINISHED" and job.status != "CANCELED" then + all_jobs_finished = false + end + # check there is some error or cancel + if stop_status == "FINISHED" and + (job.status == "ERROR" or job.status == "CANCELED") then + # write url + write_log_url(job) + # cancel all other un-finished jobs + @sub_jobs.each do |sub| + if sub.status != "ERROR" and sub.status != "FINISHED" and + sub.status != "CANCELED" and sub.cancel_state == "NONE" then + @log.info(" * Sub-Job \"#{sub.get_project().name}(#{sub.os})\" has entered \"CANCELING\" state. (#{sub.id})", Log::LV_USER) + sub.cancel_state = "INIT" + end + end + + stop_status = job.status + break + end + end + + # + sleep 1 + end + + if stop_status == "ERROR" or stop_status == "CANCELED" then + @status = stop_status + return + end + + # upload + if not upload() then + @status = "ERROR" + return + end + + # INFO. don't change this string + @log.info( "Job is completed!", Log::LV_USER) + @status = "FINISHED" + end + + + private + def upload() + @log.info( "Uploading ...", Log::LV_USER) + + # get package path list + binpkg_path_list = Dir.glob("#{@source_path}/*_*_*.zip") + + # upload + u_client = Client.new( @pkgsvr_url, nil, @log ) + snapshot = u_client.upload( @pkgsvr_ip, @pkgsvr_port, binpkg_path_list, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd) + + if snapshot.nil? then + @log.info( "Upload failed...", Log::LV_USER) + + return false + end + + # update local + @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER) + @pkgsvr_client.update + @log.info("Snapshot: #{snapshot}", Log::LV_USER) + + return true + end + + + # write web url for log + private + def write_log_url(job) + url,remote_url = job.get_log_url() + if not url.empty? then + @log.info( " ** Log1: #{url}", Log::LV_USER) + end + if not remote_url.empty? then + @log.info( " ** Log2: #{remote_url}", Log::LV_USER) + end + end + +end diff --git a/src/build_server/PackageSync.rb b/src/build_server/PackageSync.rb new file mode 100644 index 0000000..afc2598 --- /dev/null +++ b/src/build_server/PackageSync.rb @@ -0,0 +1,238 @@ +=begin + + PackageSync.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "fileutils" +require "thread" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "Action.rb" +require "ScheduledActionHandler.rb" + + +class PackageSyncAction < Action + attr_accessor :pkgsvr_url, :dist_name + @@new_id = 0 + + def initialize( time, url, dist_name, server ) + super(time, server.pkg_sync_period) + my_id = @@new_id + @@new_id += 1 + @pkgsvr_url = url + @dist_name = dist_name + @server = server + @pkgsvr_client = nil + @main_client = nil + @sync_root = "#{@server.path}/sync/#{my_id}" + @download_path = "#{@sync_root}/remote" + @original_path = "#{@sync_root}/main" + end + + + def init + # create directory + if File.exist? @download_path then + FileUtils.rm_rf @download_path + FileUtils.rm_rf @original_path + end + + FileUtils.mkdir_p @download_path + FileUtils.mkdir_p @original_path + + # create client + @pkgsvr_client = Client.new( @pkgsvr_url, @download_path, @server.log ) + + main_url = @server.distmgr.get_distribution(@dist_name).pkgsvr_url + @main_client = Client.new( main_url, @original_path, @server.log ) + end + + + def execute + @server.log.info "Executing package-sync action for server \"#{@pkgsvr_url}\"" + + begin + execute_internal() + rescue => e + @server.log.error e.message + @server.log.error e.backtrace.inspect + end + end + + + private + def execute_internal() + # check update + pkgs = check_package_update + + # request to register + registered_jobs = [] + + # if updates are found, download them + downloaded_files = [] + pkgs.each do |pkg| + pkg_name=pkg[0]; os=pkg[1]; prj=pkg[2] + + file_paths = @pkgsvr_client.download(pkg_name, os, false) + if file_paths.nil? then next end + downloaded_files += file_paths + + file_paths.each do |file_path| + @server.log.info "Creating new job for registering \"#{file_path}\"" + new_job = @server.jobmgr.create_new_register_job( file_path, @dist_name ) + if new_job.nil? then + @server.log.error "Creating job failed: #{prj.name} #{pkg_name} #{@dist_name}" + next + end + new_job.priority = CommonJob::AUTO_JOB_PRIORITY + new_job.create_logger( nil ) + + # add + @server.jobmgr.add_job( new_job ) + registered_jobs.push new_job + end + end + + # wait for finish all jobs + all_jobs_finished = false + while not all_jobs_finished + unfinished_jobs = registered_jobs.select do |j| + (j.status != "ERROR" and j.status != "FINISHED" and j.status != "CANCELED") + end + if unfinished_jobs.empty? then + all_jobs_finished = true + else + sleep 10 + end + end + + # remove files + downloaded_files.each do |file_path| + @server.log.info "Removed downloaded file: \"#{file_path}\"" + FileUtils.rm_rf file_path + end + end + + + protected + def check_package_update + pkgs = [] + + # update + @pkgsvr_client.update() + @main_client.update() + + # for all BINARY project + bin_prjs = @server.prjmgr.get_all_projects().select { |p| + (p.type == "BINARY" and p.dist_name == @dist_name) + } + bin_prjs.each do |p| + pkg_name = p.pkg_name + p.os_list.each do |os| + # get pkg version in server + main_ver = @main_client.get_attr_from_pkg(pkg_name, os, "version") + remote_ver = @pkgsvr_client.get_attr_from_pkg(pkg_name, os, "version") + if remote_ver.nil? then next end + + if main_ver.nil? or Version.new(main_ver) < Version.new(remote_ver) then + pkgs.push [pkg_name, os, p] + end + end + end + + return pkgs + end + +end + + +class PackageServerSynchronizer + attr_accessor :quit + + # init + def initialize( server ) + @server = server + @handler = ScheduledActionHandler.new + end + + + # start thread + def start() + + # start thread for handling action + @handler.start + + Thread.new do + monitor() + end + end + + + private + def monitor() + while(true) + # wait 10 seconds + sleep 10 + + # get info from DB + syncs = @server.get_sync_package_servers() + + # check removal + @handler.get_actions().each do |act| + exist = false + syncs.each do |sync| + url=sync[0]; dist_name=sync[1] + if url == act.pkgsvr_url and dist_name == act.dist_name then + exist = true + break + end + end + if not exist then + @handler.unregister(act) + @server.log.info "Unregistered package-sync action!: #{act.dist_name} <= \"#{act.pkgsvr_url}\"" + end + end + + # check add/modify + syncs.each do |sync| + url=sync[0]; dist_name=sync[1] + exist = false + @handler.get_actions().each do |act| + if act.pkgsvr_url == url and act.dist_name == dist_name then + exist = true + end + end + + if not exist then + new_time = Time.new + 10 + @handler.register( PackageSyncAction.new(new_time, url, dist_name, @server) ) + @server.log.info "Registered package-sync action!: #{dist_name} <= \"#{url}\"" + end + end + + end + end +end diff --git a/src/build_server/ProjectManager.rb b/src/build_server/ProjectManager.rb new file mode 100644 index 0000000..c717213 --- /dev/null +++ b/src/build_server/ProjectManager.rb @@ -0,0 +1,364 @@ +=begin + + ProjectManager.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +require 'dbi' +$LOAD_PATH.unshift File.dirname(__FILE__) +require "GitBuildProject.rb" +require "BinaryUploadProject.rb" +require "MultiBuildJob.rb" +require "PackageManifest.rb" +require "package.rb" + +class ProjectManager + + # initialize + def initialize( server ) + @server = server + @project_root = "#{@server.path}/projects" + end + + + # load existing project from server configuration + def load() + # check project root + if not File.exist? @project_root then + FileUtils.mkdir_p @project_root + end + end + + + # get_project of the name + def get_project(name, dist_name) + @server.get_db_connection() do |db| + return get_project_internal(name, dist_name, db) + end + + return nil + end + + + def get_all_projects_summary() + @server.get_db_connection() do |db| + return CommonProject.get_all_project_rows(db) + end + end + + def get_all_projects() + result = [] + + @server.get_db_connection() do |db| + rows = CommonProject.get_all_project_rows(db) + rows.each do |row| + if row[:ptype] == "GIT" then + prj = GitBuildProject.load(row[:name], row[:dist_name], @server, db) + else + prj = BinaryUploadProject.load(row[:name], row[:dist_name], @server, db) + end + if not prj.nil? then result.push prj end + end + return result + end + + return result + end + + + def add_git_project(name, repos, branch, passwd, os_list, dist_name) + new_prj = nil + result = @server.get_db_connection() do |db| + prj = get_project_internal(name, dist_name, db) + if not prj.nil? then + @server.log.error "Adding project failed!: the project \"#{name}\"(#{dist_name}) already exists" + return false + end + + # create new object + new_prj = GitBuildProject.new(name, @server, os_list, dist_name, repos, branch) + if not passwd.nil? and not passwd.empty? then + new_prj.passwd = passwd + end + + # save to db + new_prj.save(db) + end + + if result then + # authorize admin to access + @server.qualify_admin_to_access(new_prj.get_project_id()) + @server.log.info "Added new GIT project \"#{name}\"(#{dist_name})" + end + + return result + end + + + def add_binary_project(name, pkg_name, passwd, os_list, dist_name) + new_prj = nil + result = @server.get_db_connection() do |db| + prj = get_project_internal(name, dist_name, db) + if not prj.nil? then + @server.log.error "Adding project failed!: the project \"#{name}\"(#{dist_name}) already exists" + return false + end + + # create new object + new_prj = BinaryUploadProject.new(name, @server, os_list, dist_name, pkg_name) + if not passwd.nil? and not passwd.empty? then + new_prj.passwd = passwd + end + + # save to db + new_prj.save(db) + + # init + new_prj.init() + end + + if result then + # authorize admin to access + @server.qualify_admin_to_access(new_prj.get_project_id()) + @server.log.info "Added new BINARY project \"#{name}\"(#{dist_name})" + end + + return result + end + + + def remove_project( name, dist_name ) + + result = @server.get_db_connection() do |db| + prj = get_project_internal(name, dist_name, db) + if prj.nil? then + @server.log.error "The project \"#{name}\"(#{dist_name}) does not exists on server" + @server.log.error "Removing project failed!" + return false + end + # unload from DB + prj.unload(db) + + # remove project directory + FileUtils.rm_rf prj.path + end + + if result then + @server.log.info "Removed the project \"#{name}\"(#{dist_name})" + end + return result + end + + public + def get_project_accessable(project_name, dist_name, user_id) + prj = get_project(project_name, dist_name) + result = nil + @server.get_db_connection() do |db| + result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses + WHERE user_groups.user_id = #{user_id} and + user_groups.group_id = group_project_accesses.group_id and + group_project_accesses.project_id = #{prj.get_project_id} and + group_project_accesses.build = 'TRUE'" + end + return (not result.nil?) + end + + def get_project_pkg_name_accessable(pkg_name, dist_name, user_id) + result = nil + prj = get_project_from_package_name(pkg_name, dist_name) + @server.get_db_connection() do |db| + result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses + WHERE user_groups.user_id = #{user_id} and + user_groups.group_id = group_project_accesses.group_id and + group_project_accesses.project_id = #{prj.get_project_id} and + group_project_accesses.build = 'TRUE'" + end + return (not result.nil?) + end + + # create new job for project + # if cannot create, return nil + def create_new_job( name, os, dist_name ) + prj = get_project( name, dist_name ) + if prj.nil? then + @server.log.error "Cannot get project info \"#{name}\"(#{dist_name})" + end + + return prj.create_new_job( os ) + end + + + # create new multi build job + def create_new_multi_build_job( sub_job_list ) + result = MultiBuildJob.new( @server ) + + sub_job_list.each do |job| + result.add_sub_job( job ) + end + + return result + end + + + # create new full job + def create_new_full_build_job(dist_name="BASE") + # create multi job + result = MultiBuildJob.new( @server ) + + # create sub jobs + get_all_projects().each do |prj| + if prj.type != "GIT" then next end + if prj.dist_name != dist_name then next end + + prj.os_list.each do |os| + if not @server.supported_os_list.include? os then next end + + new_job = create_new_job( prj.name, os, dist_name ) + if new_job.nil? then next end + + # This make project to build + # even though there is a package of same version on pkg-server + new_job.set_force_rebuild(true) + + # add to multi job + result.add_sub_job( new_job ) + end + end + + return result + end + + + # get project that includes specified pkg name and os + # will return [project,os,ver] list + def get_projects_from_pkgs(pkgs, dist_name="BASE") + result = [] + get_all_projects().each do |prj| + # check distribution name + if prj.dist_name != dist_name then next end + + pkgs.each do |pkg| + name = pkg.package_name + ver = pkg.version + os = pkg.os + + # check project provide target package + if prj.include_package?(name, ver, os) then + result.push [prj, os, ver] + break + end + end + end + + return result + end + + + def get_project_from_package_name(pkg_name, dist_name) + @server.get_db_connection() do |db| + return get_project_from_pkg_name_internal(pkg_name,dist_name,db) + end + return nil + end + + + # get project from git repository + def get_git_project( repos, dist_name ) + get_all_projects().each do |prj| + # check project's distribution + if prj.dist_name != dist_name then next end + if prj.type == "GIT" and prj.repository == repos then + return prj + end + end + + return nil + end + + + def create_unnamed_git_project(repos, dist_name) + name = "UNNAMED_PRJ_#{get_all_projects().count}" + branch = "master" + passwd = nil + os_list = Utils.get_all_OSs() + os_list.each do |os| + @server.add_supported_os(os) + end + # add + add_git_project(name , repos, branch, passwd, os_list, dist_name) + # get + return get_project(name, dist_name) + end + + + # write configuration + def write_configuration(name, repos, branch, passwd, os_list ) + config_file = "#{@project_root}/#{name}/build" + File.open( config_file, "w" ) do |f| + f.puts "TYPE=GIT" + if not passwd.nil? and not passwd.empty? then + f.puts "PASSWD=#{passwd}" + end + f.puts "GIT_REPOSITORY=#{repos}" + f.puts "GIT_BRANCH=#{branch}" + f.puts "OS_LIST=#{os_list.join(",")}" + end + end + + + # write configuration + def write_configuration_for_binary_project(name, pkg_name, passwd, os_list ) + config_file = "#{@project_root}/#{name}/build" + File.open( config_file, "w" ) do |f| + f.puts "TYPE=BINARY" + if not passwd.nil? and not passwd.empty? then + f.puts "PASSWD=#{passwd}" + end + f.puts "PACKAGE_NAME=#{pkg_name}" + f.puts "OS_LIST=#{os_list.join(",")}" + end + end + + + private + def get_project_internal(name, dist_name, db) + row = CommonProject.get_project_row(name, dist_name, db) + if row.nil? then return nil end + prj_type = row['ptype'] + + if prj_type == "GIT" then + return GitBuildProject.load(name, dist_name, @server, db) + else + return BinaryUploadProject.load(name, dist_name, @server, db) + end + end + + private + def get_project_from_pkg_name_internal(pkg_name, dist_name, db) + row = CommonProject.get_project_from_pkg_name_row(pkg_name, dist_name, db) + return ( row.nil? ) ? nil : BinaryUploadProject.load(row[:name], dist_name, @server, db) + end +end diff --git a/src/build_server/RegisterPackageJob.rb b/src/build_server/RegisterPackageJob.rb new file mode 100644 index 0000000..b745a3c --- /dev/null +++ b/src/build_server/RegisterPackageJob.rb @@ -0,0 +1,549 @@ +=begin + + RegisterBinaryJob.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "fileutils" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/builder" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/plkg_server" +require "client.rb" +require "PackageManifest.rb" +require "Version.rb" +require "JobLog.rb" +require "mail.rb" +require "utils.rb" +require "ReverseBuildChecker.rb" +require "CommonJob.rb" + +class RegisterPackageJob < CommonJob + + attr_accessor :source_path + attr_accessor :pkgsvr_client, :thread, :pkg_type + attr_accessor :pkg_name, :pkginfo, :cancel_state + attr_accessor :no_reverse + + + # initialize + def initialize( local_path, project, server, ftpurl=nil, dist_name=nil ) + super(server) + @log = nil + @type = "REGISTER" + @no_reverse = false + + @host_os = Utils::HOST_OS + if not project.nil? then + @pkgsvr_url = @server.distmgr.get_distribution(project.dist_name).pkgsvr_url + @pkgsvr_ip = @server.distmgr.get_distribution(project.dist_name).pkgsvr_ip + @pkgsvr_port = @server.distmgr.get_distribution(project.dist_name).pkgsvr_port + else + @pkgsvr_url = @server.distmgr.get_distribution(dist_name).pkgsvr_url + @pkgsvr_ip = @server.distmgr.get_distribution(dist_name).pkgsvr_ip + @pkgsvr_port = @server.distmgr.get_distribution(dist_name).pkgsvr_port + end + @job_root = "#{@server.path}/jobs/#{@id}" + @source_path = @job_root+"/temp" + @job_working_dir=@job_root+"/works" + @buildroot_dir = "#{@job_root}/buildroot" + @cancel_state = "NONE" + + @local_path=local_path + @file_path = nil + @filename = File.basename(local_path) + if @filename =~ /.*_.*_.*\.zip/ then + @pkg_type = "BINARY" + new_name = @filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + @pkg_name = new_name.split(",")[0] + @pkg_version = new_name.split(",")[1] + @os = new_name.split(",")[2] + else + @pkg_type = "ARCHIVE" + @pkg_name = @filename + end + @pkginfo = nil #This info is valid only for BINARY package + @project = project + if not dist_name.nil? then + @dist_name = dist_name + elsif not @project.nil? then + @dist_name = @project.dist_name + else + @dist_name = "BASE" + end + @auto_remove = false + end + + + def get_distribution_name() + return @dist_name + end + + + def get_buildroot() + return @buildroot_dir + end + + + def is_rev_build_check_job() + return false + end + + + def set_auto_remove(value) + @auto_remove=value + end + + + def set_no_reverse() + @no_reverse = true + end + + + # + def init + # mkdir + if not File.exist? @job_root then + FileUtils.mkdir_p @job_root + end + + if @cancel_state != "NONE" then return false end + + # create logger + if @log.nil? then + @log = JobLog.new(self, nil ) + end + + if @cancel_state != "NONE" then return false end + + @log.info( "Initializing job...", Log::LV_USER) + + # create dummy source path + if not File.exist? @source_path then + FileUtils.mkdir_p @source_path + end + + # copy package file to source path + @file_path = "#{@source_path}/#{File.basename(@local_path)}" + if not File.exist? @local_path then + @log.error( "File not found!", Log::LV_USER) + @status = "ERROR" + return false + else + if @auto_remove then + # if remote upload remove file and its directory + FileUtils.mv(@local_path, @file_path) + FileUtils.rm_rf("#{File.dirname(@local_path)}") + else + FileUtils.cp(@local_path, @file_path) + end + end + + if @cancel_state != "NONE" then return false end + + # set up pkgsvr_client + @pkgsvr_client = Client.new(@pkgsvr_url, @job_working_dir, @log) + + if @cancel_state != "NONE" then return false end + + # check if the os is supported by build server + if @pkg_type == "BINARY" and + not @server.supported_os_list.include? @os then + @log.error( "Unsupported OS \"#{@os}\" is used!", Log::LV_USER) + @status = "ERROR" + return false + end + + if @cancel_state != "NONE" then return false end + + # checking version if not reverse-build job + if @pkg_type == "BINARY" then + # extrac pkg file + cmd = "cd \"#{@source_path}\";unzip #{@file_path}" + if not Utils.execute_shell(cmd) then + @log.error( "Extracting package file failed!", Log::LV_USER) + @status = "ERROR" + return false + end + + if @cancel_state != "NONE" then return false end + + # set up pkg info + begin + @pkginfo = PackageManifest.new("#{@source_path}/pkginfo.manifest") + rescue => e + @log.error( e.message, Log::LV_USER) + @status = "ERROR" + return false + end + + #if @server.changelog_check and not @pkginfo.packages[0].does_change_exist? then + # @log.error( "change log not found", Log::LV_USER ) + # return false + #end + + if @cancel_state != "NONE" then return false end + + if not check_package_version() then + @status = "ERROR" + return false + end + end + + if @cancel_state != "NONE" then return false end + + return true + end + + + #terminate + def terminate() + # report error + if @status == "ERROR" then + @log.error( "Job is stopped by ERROR" , Log::LV_USER) + @server.cleaner.clean_afterwards(@id) + else + @log.info( "Job is FINISHED successfully!" , Log::LV_USER) + + # if succeeded, register source info and copy pkginfo.manifest + if not @project.nil? then + @log.info( "Updating the source info for project \"#{@project.name}\"" , Log::LV_USER) + @project.save_source_info( @pkginfo.get_version(), '') + @project.save_package_info_from_manifest( @pkginfo.get_version(),"#{@source_path}/pkginfo.manifest", @os) + end + + # clean up + @server.cleaner.clean(@id) + end + + # close logger + @log.close + end + + + #cancel + def cancel() + if not @log.nil? then + @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER) + end + end + + + # check building is possible + def can_be_built_on?(host_os) + return true + end + + + def get_packages() + if @pkg_type == "BINARY" then + return @pkginfo.packages + else + return [] + end + end + + + def get_build_dependencies(target_os) + return [] + end + + + def get_source_dependencies(target_os,host_os) + return [] + end + + + def is_compatible_with?(o) + return false + end + + + def has_build_dependency?(other_job) + if has_same_packages?(other_job) or + does_depended_by?(other_job) then + + return true + else + return false + end + end + + + def has_same_packages?( wjob ) + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + if @type != wjob.type then return false end + + case @pkg_type + when "BINARY" + if @pkg_name == wjob.pkg_name and + @os == wjob.os then + return true + end + when "ARCHIVE" + if @pkg_name == wjob.pkg_name then return true end + end + + return false + end + + + # binary/archive package should not have build-dependencies + def does_depend_on?( wjob ) + return false + end + + + def does_depended_by?( wjob ) + # must have same distribution + if get_distribution_name() != wjob.get_distribution_name() then + return false + end + + if @pkg_type == "BINARY" then + wjob.get_build_dependencies(wjob.os).each do |dep| + # dep package of working job must have same name and target os + # with packages in my job + if dep.package_name == @pkg_name and + dep.target_os_list.include? @os then + #puts "Checking... A <- B" + return true + end + end + else + wjob.get_source_dependencies(wjob.os,@host_os).each do |dep| + if dep.package_name == @pkg_name then + return true + end + end + end + + return false + end + + + def is_connected? + return true + end + + + # return the job is asyncronous job + def is_asynchronous_job? + return false + end + + + def progress + return "" + end + + + def get_log_url() + # only when server support log url + if @server.job_log_url.empty? then + return "","" + end + + return "#{@server.job_log_url}/#{@id}/log","" + end + + # + # PROTECTED METHODS + # + + + # main module + protected + def job_main() + @log.info( "Invoking a thread for REGISTER Job #{@id}", Log::LV_USER) + if @status == "ERROR" then return end + @log.info( "New Job #{@id} is started", Log::LV_USER) + + # clean build + if not ReverseBuildChecker.check( self, true ).empty? then + @status = "ERROR" + @log.error( "Reverse-build-check failed!" ) + return + end + + # if this package has compatible OS, check + if @pkg_type == "BINARY" and + @pkginfo.packages[0].os_list.count > 1 then + + pkg = @pkginfo.packages[0] + pkg.os_list.each do |os| + if @os == os then next end + + # skip when the os does not exist in project's supported os list + if not @project.nil? and not @project.os_list.include? os then next end + + # skip when there is higher version of the package + ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version") + if not ver_svr.nil? and + Version.new(@pkg_version) <= Version.new(ver_svr) then next end + + # make new package file for compatible OS + newfile = "#{@pkg_name}_#{@pkg_version}_#{os}.zip" + @log.info( "Copying #{@filename} to #{newfile}" ) + FileUtils.cp(@file_path,"#{@source_path}/#{newfile}") + + # reverse check + if not @no_reverse then + if not ReverseBuildChecker.check( self, true, os ) then + @status = "ERROR" + @log.error( "Reverse-build-check failed!" ) + return + end + end + end + end + + # upload + if not upload() then + @status = "ERROR" + return + end + + # INFO. don't change this string + @log.info( "Job is completed!", Log::LV_USER) + @status = "FINISHED" + end + + + # build projects that dependes on me + # can ignore some projects + def check_reverse_build( target_os ) + @log.info( "Checking reverse build dependency ...", Log::LV_USER) + + # get reverse-dependent projects + rev_pkgs = [] + if @pkg_type == "BINARY" then + rev_pkgs += @pkgsvr_client.get_reverse_build_dependent_packages(@pkg_name, target_os) + else + rev_pkgs += @pkgsvr_client.get_reverse_source_dependent_packages(@pkg_name) + end + + rev_projects = @server.prjmgr.get_projects_from_pkgs(rev_pkgs, get_distribution_name()) + + # create reverse build job + rev_build_jobs = [] + rev_projects.each do |p| + prj = p[0] + os = p[1] + version = p[2] + + if prj.type != "GIT" then next end + + # create sub jobs for checking + new_job = prj.create_new_job_from_version(os, version) + new_job.set_rev_build_check_job(self) + + rev_build_jobs.push new_job + end + + # reverse build + if rev_build_jobs.count > 0 then + rev_prjs_txt = rev_build_jobs.map {|j| "#{j.get_project().name}(#{j.os})"}.join(", ") + @log.info( " * Will check reverse-build for next projects: #{rev_prjs_txt}", Log::LV_USER) + end + rev_build_jobs.each do |new_job| + @log.info( " * Checking reverse-build ... #{new_job.get_project().name}(#{new_job.id})", Log::LV_USER) + # job init + result = new_job.init() + # if init is succeeded!, try to execute + if result then + # check available server + rserver = @server.get_available_server( new_job ) + if rserver != nil and rserver != @server then + new_job.set_remote_job( rserver ) + end + # execute + new_job.execute(true) + if new_job.status == "ERROR" then result = false end + end + + # check result + if not result then + return false + end + end + + return true + end + + + def upload() + @log.info( "Uploading ...", Log::LV_USER) + + # get package path list + if @pkg_type == "ARCHIVE" then + binpkg_path_list = Dir.glob("#{@source_path}/#{@pkg_name}") + else + binpkg_path_list = Dir.glob("#{@source_path}/*_*_*.zip") + end + + # upload + u_client = Client.new( @pkgsvr_url, nil, @log ) + snapshot = u_client.upload( @pkgsvr_ip, @pkgsvr_port, binpkg_path_list, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd) + + if snapshot.nil? then + @log.info( "Upload failed...", Log::LV_USER) + + return false + end + + # update local + @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER) + @pkgsvr_client.update + @log.info("Snapshot: #{snapshot}", Log::LV_USER) + + return true + end + + + # check if local package version is greater than server + def check_package_version() + @log.info( "Checking package version ...", Log::LV_USER) + + # package update + @pkgsvr_client.update + + @pkginfo.packages.each do |pkg| + ver_local = pkg.version + #ver_svr = @pkgsvr_client.get_package_version( pkg.package_name, @os ) + ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version") + if not ver_svr.nil? and Version.new(ver_local) <= Version.new(ver_svr) then + @log.error( "Version must be increased : #{ver_local} <= #{ver_svr}", Log::LV_USER) + return false + end + end + + return true + end +end diff --git a/src/build_server/RemoteBuildJob.rb b/src/build_server/RemoteBuildJob.rb index 8e9355b..4645786 100644 --- a/src/build_server/RemoteBuildJob.rb +++ b/src/build_server/RemoteBuildJob.rb @@ -1,5 +1,5 @@ =begin - + RemoteBuildJob.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -31,14 +31,15 @@ $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" require "BuildJob.rb" require "utils.rb" + class RemoteBuildJob < BuildJob attr_accessor :id # initialize - def initialize (id) - super() + def initialize (id,server) + super(nil,nil,server) + # overide id @id = id @type = nil - @outstream = nil end end diff --git a/src/build_server/RemoteBuildServer.rb b/src/build_server/RemoteBuildServer.rb new file mode 100644 index 0000000..b038be1 --- /dev/null +++ b/src/build_server/RemoteBuildServer.rb @@ -0,0 +1,248 @@ +=begin + + RemoteBuildServer.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +$LOAD_PATH.unshift File.dirname(__FILE__) +require "RemoteBuildJob.rb" +require "BuildComm.rb" +require 'thread' + +class RemoteBuildServer + attr_accessor :id, :ip, :port, :description, :status, :host_os + attr_accessor :max_working_jobs, :working_jobs, :waiting_jobs, :working_job_count, :waiting_job_count + attr_accessor :path + attr_accessor :jobmgr, :distmgr + + # initialize + def initialize(ip, port, desc) + @id = -1 + @ip = ip + @port = port + @description = desc + @status = "DISCONNECTED" + @host_os = Utils::HOST_OS + @max_working_jobs = 2 + @working_jobs = [] + @working_job_count = 0 + @waiting_jobs = [] + @waiting_job_count = 0 + @path = "" + @file_transfer_cnt_mutex = Mutex.new + @file_transfer_cnt = 0 + @jobmgr = nil + @distmgr = nil + end + + + # check the job can be built on this server + def can_build?(job) + + # check me + if job.can_be_built_on? @host_os then + return true + end + + return false + end + + + # query remote server info & update server state + def update_state(db) + + # send + #@status = "DISCONNECTED" + client = BuildCommClient.create( @ip, @port ) + if client.nil? then + @status = "DISCONNECTED" + db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}" + return + end + if client.send("QUERY|SYSTEM") then + result = client.read_lines do |l| + tok = l.split(",").map { |x| x.strip } + @host_os = tok[0] + @max_working_jobs = tok[1].to_i + @status = "RUNNING" + end + if not result then @status = "DISCONNECTED" end + else + @status = "DISCONNECTED" + end + client.terminate + if @status == "DISCONNECTED" then + db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}" + return + end + + # send + @working_jobs = [] + @waiting_jobs = [] + client = BuildCommClient.create( @ip, @port ) + if client.nil? then + @status = "DISCONNECTED" + db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}" + return + end + if client.send("QUERY|JOB") then + result = client.read_lines do |l| + tok = l.split(",").map { |x| x.strip } + + job_status = tok[0] + job_id = tok[1] + new_job = RemoteBuildJob.new(job_id,self) + case job_status + when "WAITING", "JUST_CREATED", "INITIALIZING" + @waiting_jobs.push new_job + when "WORKING" + @working_jobs.push new_job + else + #puts "Uncontrolled status" + end + end + if not result then @status = "DISCONNECTED" end + else + @status = "DISCONNECTED" + end + client.terminate + if @status == "DISCONNECTED" then + db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}" + else + @working_job_count = @working_jobs.count + @waiting_job_count = @waiting_jobs.count + db.do "UPDATE remote_build_servers SET + status = '#{@status}', + supported_os_id = (SELECT supported_os.id FROM supported_os WHERE supported_os.name = '#{@host_os}'), + max_job_count = #{@max_working_jobs}, + working_job_count = #{@working_job_count}, + waiting_job_count = #{@waiting_job_count} WHERE id = #{@id}" + end + end + + + # return available working slot + def get_number_of_empty_room + return @max_working_jobs - @working_job_count + end + + + # check there are working jobs + def has_working_jobs + return (@working_job_count > 0) + end + + + # check there are waiting jobs + def has_waiting_jobs + return (@waiting_job_count > 0) + end + + + def add_file_transfer() + @file_transfer_cnt_mutex.synchronize do + @file_transfer_cnt += 1 + end + end + + def remove_file_transfer() + @file_transfer_cnt_mutex.synchronize do + @file_transfer_cnt -= 1 + end + end + + def get_file_transfer_cnt() + return @file_transfer_cnt + end + + + def set_id(id) + @id = id + end + + + def self.create_table(db, inc, post_fix) + db.do "CREATE TABLE remote_build_servers ( + id INTEGER PRIMARY KEY #{inc}, + svr_addr VARCHAR(64) NOT NULL UNIQUE, + description VARCHAR(256), + status VARCHAR(32), + supported_os_id INTEGER, + max_job_count INTEGER, + working_job_count INTEGER, + waiting_job_count INTEGER, + CONSTRAINT fk_remote_build_servers_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ) )#{post_fix}" + end + + + def self.load(ip, port, db) + saddr="#{ip}:#{port}" + row = db.select_one("SELECT remote_build_servers.*,supported_os.name as host_os_name FROM remote_build_servers, supported_os WHERE svr_addr='#{saddr}' and remote_build_servers.supported_os_id = supported_os.id") + if not row.nil? then + return load_row(row) + end + + return nil + end + + + def self.load_all(db) + result = [] + rows = db.select_all("SELECT *,'' as host_os_name FROM remote_build_servers WHERE supported_os_id IS NULL + UNION ALL + SELECT remote_build_servers.*, supported_os.name as host_os_name FROM remote_build_servers, supported_os WHERE remote_build_servers.supported_os_id = supported_os.id") + rows.each do |row| + result.push load_row(row) + end + + return result + end + + + def self.load_row(row) + svr_ip,svr_port=row['svr_addr'].strip.split(":") + new_obj = new(svr_ip, svr_port, row['description'] ) + new_obj.set_id( row['id'] ) + new_obj.status = row['status'] + new_obj.max_working_jobs =row['max_job_count'] + new_obj.working_job_count =row['working_job_count'] + new_obj.waiting_job_count =row['waiting_job_count'] + new_obj.host_os = row['host_os_name'] + return new_obj + end + + + def unload(db) + db.do("DELETE FROM remote_build_servers WHERE id=#{@id}") + end + + + def save(db) + saddr="#{@ip}:#{@port}" + db.do "INSERT INTO remote_build_servers (svr_addr,description) VALUES ('#{saddr}','#{@description}')" + end +end + diff --git a/src/build_server/RemoteBuilder.rb b/src/build_server/RemoteBuilder.rb new file mode 100644 index 0000000..78d3fa9 --- /dev/null +++ b/src/build_server/RemoteBuilder.rb @@ -0,0 +1,259 @@ +=begin + + RemoteBuilder.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server" +require "utils" +require "PackageManifest" +require "log" +require "FileTransferViaFTP" +require "FileTransferViaDirect" + +class RemoteBuilder + attr_accessor :id, :log + + # initialize + def initialize( id, server,ftp_addr, ftp_port, ftp_username, ftp_passwd) + @id = id + @server = server + @addr = server.ip + @port = server.port + @ftp_addr = ftp_addr + @ftp_port = ftp_port + @ftp_username = ftp_username + @ftp_passwd = ftp_passwd + @log = DummyLog.new + @job = nil + end + + + # build_job + def build_job( job, local_pkgs ) + # set job + @job = job + old_log = @log + @log = job.log + + # build + ret = build(@job.get_project().repository, @job.source_path, @job.os, + @job.is_rev_build_check_job(), @job.git_commit, @job.no_reverse, + local_pkgs, @job.get_project().dist_name,"admin@user" ) + + # reset job + @job = nil + @log = old_log + + # return + return ret + end + + + # build + def build( git_repos, source_path, os, is_rev_build, srcinfo, no_reverse, local_pkgs, dist_name, user_email ) + @log.info( "Start to build on remote server...", Log::LV_USER ) + + # create unique dock number + dock = Utils.create_uniq_name() + + # send local packages + begin + @server.add_file_transfer() + local_pkgs.each do |pkg_path| + @log.info( "Sending file... : #{pkg_path}", Log::LV_USER ) + result = send_file_to_remote( pkg_path, dock ) + if not result then + @log.error( "File transfering failed!", Log::LV_USER ) + @server.remove_file_transfer() + return false + end + end + ensure + @server.remove_file_transfer() + end + + # send build request + @log.info( "Sending build request to remote server...", Log::LV_USER ) + result, result_files = send_build_request(git_repos, os, is_rev_build, + srcinfo, no_reverse, local_pkgs, dock, dist_name, user_email, @log.is_verbose) + + @log.info( "Receiving log file from remote server...", Log::LV_USER ) + if not receive_file_from_remote( "#{source_path}/../remote_log", dock ) then + @log.warn( "File transfering failed! : remote_log", Log::LV_USER ) + end + + if not result then + @log.error( "Building job on remote server failed!", Log::LV_USER ) + return false + end + + # receive binary package + result_files.each do |file_name| + @log.info( "Receiving file from remote server : #{file_name}", Log::LV_USER ) + result = receive_file_from_remote( "#{source_path}/#{file_name}", dock ) + if not result then + @log.error( "File transfering failed! : #{file_name}", Log::LV_USER ) + return false + end + end + + return true + end + + + # upload binary packages that is need to be overwrite + # before remote package + protected + def send_file_to_remote(file_path, dock = "0") + # create client + client = BuildCommClient.create( @addr, @port, @log ) + if client.nil? then + @log.error( "Creating communication client failed!", Log::LV_USER) + return false + end + + # upload file + result = true + file_name = file_path.split("/")[-1] + msg = "UPLOAD|#{dock}" + if client.send( msg ) then + if not @ftp_addr.nil? then + transporter=FileTransferFTP.new(@log, @ftp_addr, @ftp_port, @ftp_username, @ftp_passwd) + else + transporter=FileTransferDirect.new(@log) + end + + result=client.send_file( file_path, transporter ) + if not result then + @log.error( "File uploading failed...#{file_name}", Log::LV_USER) + end + end + + #close connections + client.terminate + + return result + end + + + # send build request + protected + def send_build_request(git_repos, os, is_rev_build, commit, no_reverse, local_pkgs, dock, dist_name, user_email, verbose) + result_files = [] + + client = BuildCommClient.create( @addr, @port, @log ) + if client.nil? then + @log.error( "Creating communication client failed!", Log::LV_USER) + return false, result_files + end + + # get local package names + local_pkg_names = local_pkgs.map { |path| File.basename(path) } + + # send + # 0 | 1 | 2 | 3 | 4| 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 + # format: BUILD|GIT|repository|passwd|os|async|no_reverse|dist_name|user_email|verbose|internal|rev-build|commit|pkgs|dock_num + # value : BUILD|GIT|repository| |os|NO |no_reverse|dist_name|user_email|verbose|YES |rev-build|commit|pkgs|dock_num + result = true + commit = commit.nil? ? "":commit + pkg_list = local_pkg_names.join(",") + rev = is_rev_build ? "YES":"NO" + msg = "BUILD|GIT|#{git_repos}||#{os}|NO|#{no_reverse}|#{dist_name}|#{user_email}|#{verbose}|YES|#{rev}|#{commit}|#{pkg_list}|#{dock}" + result = client.send( msg ) + if not result then + @log.error( "Communication failed! #{client.get_error_msg()}", Log::LV_USER) + return false, result_files + end + + r_job_number = Regexp.new('Added new job "([^"]*)"') + error = false + result = client.read_lines do |l| + # write log first + @log.output( l.strip, Log::LV_USER) + + # set remote job id + if not @job.nil? and @job.remote_id.nil? and l =~ r_job_number then + @job.remote_id = $1 + end + + # check build result + if l.include? "Job is stopped by ERROR" or + l.include? "Error:" then + error = true + end + + # gather result files if not reverse build + if not is_rev_build and l =~ /Creating package file \.\.\. (.*)/ then + file_name = $1 + result_files.push file_name + end + end + if not result then + @log.error( "Communication failed! #{client.get_error_msg()}", Log::LV_USER) + end + if error then result=false end + + # close socket + client.terminate + + return result, result_files + end + + + # receive binary package of remote server + protected + def receive_file_from_remote(file_path, dock = "0") + # create client + client = BuildCommClient.create( @addr, @port, @log ) + if client.nil? then + @log.error( "Creating communication client failed!", Log::LV_USER) + return false + end + + # download file + result = true + file_name = file_path.split("/")[-1] + msg = "DOWNLOAD|#{dock}|#{file_name}" + if client.send( msg ) then + if not @ftp_addr.nil? then + transporter=FileTransferFTP.new(@log, @ftp_addr, @ftp_port, @ftp_username, @ftp_passwd) + else + transporter=FileTransferDirect.new(@log) + end + result=client.receive_file(file_path, transporter) + if not result then + @log.error( "File downloading failed...#{file_name}", Log::LV_USER) + end + end + + #close connections + client.terminate + + return result + end +end diff --git a/src/build_server/ReverseBuildChecker.rb b/src/build_server/ReverseBuildChecker.rb new file mode 100644 index 0000000..49dde68 --- /dev/null +++ b/src/build_server/ReverseBuildChecker.rb @@ -0,0 +1,217 @@ +=begin + + ReverseBuildChecker.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "log" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server" +require "utils.rb" +require "client.rb" +require "JobLog.rb" +require "PackageManifest.rb" + +class ReverseBuildChecker + + # check + def ReverseBuildChecker.check( job, exit_on_error, override_os = nil ) + log = job.log + job_os = (override_os.nil?) ? job.os : override_os + + # start + log.info( "Checking reverse build dependency ...", Log::LV_USER) + + # get target packages that be checked + bin_pkg_name_list = [] + src_pkg_name_list = [] + case job.type + when "BUILD" + job.pkginfo.get_target_packages(job_os).each do |pkg| + bin_pkg_name_list.push pkg.package_name + end + when "REGISTER" + if job.pkg_type == "BINARY" then + bin_pkg_name_list.push job.pkg_name + else + src_pkg_name_list.push job.pkg_name + end + end + + # get reverse projects from build dependency + rev_pkgs = [] + bin_pkg_name_list.each do |pkg_name| + rev_pkgs += job.pkgsvr_client.get_reverse_build_dependent_packages(pkg_name, job_os) + end + src_pkg_name_list.each do |pkg_name| + rev_pkgs += job.pkgsvr_client.get_reverse_source_dependent_packages(pkg_name) + end + rev_pkgs.uniq! + rev_projects = job.server.prjmgr.get_projects_from_pkgs(rev_pkgs, job.get_distribution_name()) + + # create reverse build job + rev_build_jobs = [] + rev_projects.each do |p| + rev_prj = p[0] + rev_os = p[1] + rev_ver = p[2] + + # if not "GIT" project, ignore it + if rev_prj.type != "GIT" then next end + + # if job on resolve process, its unresolved project + #of pending ancestor must be excluded. + if job.type == "BUILD" and not job.pending_ancestor.nil? then + found = false + job.pending_ancestor.rev_fail_projects.each do |fp| + f_prj = fp[0] + f_os = fp[1] + + if rev_prj == f_prj and rev_os == f_os then + found = true + break + end + end + if found then next end + end + + # if this is sub job, all other sibling job must be excluded + if job.is_sub_job? then + job.get_parent_job().get_sub_jobs().each do |sub_job| + sub_prj = sub_job.get_project() + sub_os = sub_job.os + if rev_prj == sub_prj and rev_os == sub_os then + found = true + break + end + end + if found then next end + end + + # create job + new_job = rev_prj.create_new_job_from_version( rev_os, rev_ver ) + new_job.set_rev_build_check_job( job ) + + # set user id + new_job.user_id = job.user_id + + rev_build_jobs.push new_job + end + + # reverse build + if rev_build_jobs.count > 0 then + rev_prjs_msg = rev_build_jobs.map {|j| "#{j.get_project().name}(#{j.os})"}.join(", ") + log.info( " * Will check reverse-build for projects: #{rev_prjs_msg}", Log::LV_USER) + end + + # for all reverse job + rev_build_jobs.each do |rev_job| + # add to job manager + job.server.jobmgr.add_reverse_build_job(rev_job) + log.info( " * Added new job for reverse-build ... #{rev_job.get_project().name}(#{rev_job.os}) (#{rev_job.id})", Log::LV_USER) + end + + # wait for job finish + rev_build_finished = false + success_list = [] + failure_list = [] + cancel_other_jobs = false + while not rev_build_finished + rev_build_finished = true + rev_build_jobs.each do |rev_job| + rev_prj = rev_job.get_project() + rev_os = rev_job.os + + case rev_job.status + when "ERROR", "CANCELED" + # add fail list + if not is_project_included?(failure_list, rev_prj, rev_os) then + log.info( " * Reverse-build FAIL ... #{rev_prj.name}(#{rev_os}) (#{rev_job.id})", Log::LV_USER) + failure_list.push [ rev_prj, rev_os ] + write_log_url(log, rev_job) + end + + # if "exist on error" cancel all other jobs + if exit_on_error then + cancel_other_jobs = true + rev_build_jobs.each do |j| + if j.status != "ERROR" and j.status != "FINISHED" and + j.status != "CANCELED" and j.cancel_state == "NONE" then + + j.cancel_state = "INIT" + end + end + break + end + when "FINISHED" + # add success list + if not success_list.include? rev_job then + log.info( " * Reverse-build OK ... #{rev_prj.name}(#{rev_os}) (#{rev_job.id})", Log::LV_USER) + success_list.push rev_job + end + else + rev_build_finished = false + end + end + + sleep 1 + end + + # clean up all reverse build jobs + rev_build_jobs.each do |rev_job| + if rev_job.status == "ERROR" or rev_job.status == "CANCELED" then + rev_job.server.cleaner.clean_afterwards(rev_job.id) + else + rev_job.server.cleaner.clean(rev_job.id) + end + end + + return failure_list + end + + + private + def self.is_project_included?( prj_list, prj, os ) + prj_list.each do |p| + if p[0] == prj and p[1] == os then return true end + end + + return false + end + + + # write web url for log + private + def self.write_log_url(log, job) + url,remote_url = job.get_log_url() + if not url.empty? then + log.info( " ** Log1: #{url}", Log::LV_USER) + end + if not remote_url.empty? then + log.info( " ** Log2: #{remote_url}", Log::LV_USER) + end + end +end diff --git a/src/build_server/SocketJobRequestListener.rb b/src/build_server/SocketJobRequestListener.rb index 4cfa794..dc18da6 100644 --- a/src/build_server/SocketJobRequestListener.rb +++ b/src/build_server/SocketJobRequestListener.rb @@ -1,5 +1,5 @@ =begin - + SocketJobRequestListener.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -27,10 +27,9 @@ Contributors: =end $LOAD_PATH.unshift File.dirname(__FILE__) -require "GitBuildJob.rb" -require "LocalBuildJob.rb" require "JobLog.rb" require "BuildComm.rb" +require "BuildServerException.rb" class SocketJobRequestListener @@ -40,14 +39,23 @@ class SocketJobRequestListener @parent_server = parent @thread = nil @finish_loop = false + @comm_server = nil @log = @parent_server.log end # start listening def start() - @thread = Thread.new { - main() - } + @thread = Thread.new do + # make loop recover when unhandled exception occurred + while not @finish_loop + begin + main() + rescue => e + @log.error e.message + @log.error e.backtrace.inspect + end + end + end end @@ -56,36 +64,45 @@ class SocketJobRequestListener def stop_listening() @finish_loop = true end - + private - # thread main + # thread main def main() # server open begin - server = BuildCommServer.new(@parent_server.port, @log) + if not @parent_server.ftp_addr.nil? then + ftp_url = Utils.generate_ftp_url(@parent_server.ftp_addr, @parent_server.ftp_port, + @parent_server.ftp_username, @parent_server.ftp_passwd) + else + ftp_url = nil + end + cache_dir = "#{@parent_server.transport_path}/.cache" + @comm_server = BuildCommServer.create(@parent_server.port, @log, ftp_url, cache_dir) rescue @log.info "Server creation failed" + puts "Server creation failed" + @parent_server.stop return end # loop - @log.info "Entering Control Listening Loop ... " + @log.info "Entering Control Listening Loop ... " @finish_loop = false - server.wait_for_connection(@finish_loop) do |req| - handle_job_request( req ) - end + @comm_server.wait_for_connection(@finish_loop) do |req| + handle_job_request( req ) + end # quit - server.terminate + @comm_server.terminate end # wait for job requests def wait_for_job_requests req_list = [] - req_list.push @tcp_server.accept - + req_list.push @tcp_server.accept + return req_list end @@ -94,15 +111,18 @@ class SocketJobRequestListener def handle_job_request( req ) # read request - req_line = req.gets + req_line = req.gets if req_line.nil? then return end + # accept + BuildCommServer.send_begin(req) + # parse request cmd = "" - if req_line.split(",").count > 0 then - cmd = req_line.split(",")[0].strip + if req_line.split("|").count > 0 then + cmd = req_line.split("|")[0].strip end - + case cmd when "BUILD" handle_cmd_build( req_line, req ) @@ -110,142 +130,922 @@ class SocketJobRequestListener handle_cmd_resolve( req_line, req ) when "QUERY" handle_cmd_query( req_line, req ) + when "CANCEL" + handle_cmd_cancel( req_line, req ) + when "STOP" + handle_cmd_stop( req_line, req ) + when "UPGRADE" + handle_cmd_upgrade( req_line, req ) + when "FULLBUILD" + handle_cmd_fullbuild( req_line, req ) + when "REGISTER" + handle_cmd_register( req_line, req ) + when "DOWNLOAD" + Thread.new do + begin + handle_cmd_download( req_line, req ) + rescue => e + @log.error "Transfering file failed!" + @log.error e.message + @log.error e.backtrace.inspect + end + end + when "UPLOAD" + Thread.new do + begin + handle_cmd_upload( req_line, req ) + rescue => e + @log.error "Transfering file failed!" + @log.error e.message + @log.error e.backtrace.inspect + end + end else - @log.info "Received Unknown REQ: #{req_line}" + @log.info "Received Unknown REQ: #{req_line}" raise "Unknown request: #{req_line}" end end - # "BUILD" + # "BUILD" def handle_cmd_build( line, req ) - tok = line.split(",").map { |x| x.strip } - if tok.count < 4 then - @log.info "Received Wrong REQ: #{line}" - raise "Invalid request format is used: #{line}" + @log.info "Received REQ: #{line}" + + begin + handle_cmd_build_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) end - case tok[1] - # BUILD,GIT,repos,commit,os,url,async - when "GIT" - @log.info "Received BUILD GIT => #{tok[2]}" + @log.info "Handled REQ: #{line}" + end - # check asynchronous job - async = (not tok[6].nil? and tok[6]=="YES" ? true:false) - if async then - new_job = GitBuildJob.new( tok[2], tok[3], tok[4], tok[5], [], @parent_server, nil, nil, false) - else - new_job = GitBuildJob.new( tok[2], tok[3], tok[4], tok[5], [], @parent_server, nil, req, false) - end - BuildCommServer.send_begin(req) - # start job. If log url is supported, show it - if not @parent_server.job_log_url.empty? then - new_job.log.info( "Added new job \"#{new_job.id}\"! Check following URL", Log::LV_USER) - new_job.log.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER) - else - new_job.log.info( "Added new job \"#{new_job.id}\"!", Log::LV_USER) + def handle_cmd_build_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 3 then + raise BuildServerException.new("ERR001"), line + end + + # check type + if tok[1] != "GIT" then + raise BuildServerException.new("ERR001"), line + end + + # 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 + # Case1. BUILD|GIT|project_name|passwd|os_list|async|no_reverse|dist_name|user_email|verbose + # Case2. BUILD|GIT|git_repos | |os |async|no_reverse|dist_name|user_email|verbose|internal|rev_build|commit|pkgs|dock_num + + # parse + project_name_list = tok[2].split(",") + passwd_list = tok[3].split(",") + passwd = passwd_list[0] + os_list = tok[4].split(",") + async = tok[5].eql? "YES" + no_reverse = tok[6].eql? "YES" + dist_name = (not tok[7].nil? and not tok[7].empty?) ? tok[7].strip : "" + user_email = (not tok[8].nil? and not tok[8].empty?) ? tok[8].strip : "" + verbose = tok[9].eql? "YES" + is_internal = tok[10].eql? "YES" + rev_job = tok[11].eql? "YES" + git_commit = (not tok[12].nil? and not tok[12].empty?) ? tok[12] : nil + pkg_files = (not tok[13].nil? and not tok[13].empty?) ? tok[13].split(",") : [] + dock_num = (not tok[14].nil? and not tok[14].empty?) ? tok[14].strip : "0" + if (dist_name.nil? or dist_name.empty?) then + dist_name = @parent_server.distmgr.get_default_distribution_name() + end + + # check distribution + check_distribution(dist_name, req) + + # check supported os if not internal job + if not is_internal then + os_list = check_supported_os( os_list , req ) + end + + # check user email + user_id = @parent_server.check_user_id_from_email( user_email ) + if user_id == -1 then + raise BuildServerException.new("ERR004"), user_email + end + + + # multi build job + if project_name_list.count > 1 or os_list.count > 1 then + new_job_list = [] + i = 0 + project_name_list.each do |pname| + if not passwd_list[i].nil? then passwd = passwd_list[i] + else passwd = passwd_list[0] end + check_build_project(pname,passwd,dist_name,req) + if not check_project_user_id(pname,dist_name,user_id) then + raise BuildServerException.new("ERR005"), "#{user_email} -> #{pname}" + end + os_list.each do |os| + new_job = create_new_job( pname, os, dist_name ) + if new_job.nil? then + @log.warn "\"#{pname}\" does not support #{os}" + next + else + new_job.user_id = user_id + end + new_job_list.push new_job + @log.info "Received a request for building this project : #{pname}, #{os}" + end + i = i + 1 end - # if asynchronouse, quit connection - if async then - if not @parent_server.job_log_url.empty? then - req.puts ( "Info: Added new job \"#{new_job.id}\"! Check following URL") - req.puts ( "Info: * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log") + if new_job_list.count > 1 then + new_job = @parent_server.prjmgr.create_new_multi_build_job( new_job_list ) + if new_job.nil? then + raise BuildServerException.new("ERR006"),"Multi-Build job" else - req.puts( "Info: Added new job \"#{new_job.id}\"!") + new_job.user_id = user_id end + elsif new_job_list.count == 1 then + new_job = new_job_list[0] + else + raise BuildServerException.new("ERR006"),"No valid sub jobs in Multi-Build job" + end - BuildCommServer.send_end(req) - BuildCommServer.disconnect(req) - end + # transfered job + elsif is_internal then + git_repos = project_name_list[0] + os = os_list[0] - # add - @parent_server.add_job( new_job ) - - # BUILD,LOCAL,path,os,url - when "LOCAL" - @log.info "Received BUILD LOCAL => #{tok[2]}" - - BuildCommServer.send_begin(req) - @parent_server.add_job( - LocalBuildJob.new( tok[2], tok[3], tok[4], [], @parent_server, nil, req, false)) + new_job = create_new_internal_job(git_repos, os, git_commit, pkg_files, dock_num, dist_name ) + if new_job.nil? then + raise BuildServerException.new("ERR006"),"Transfered-Build job" + else + new_job.user_id = user_id + end + if rev_job then new_job.set_rev_build_check_job(nil) end + + # single job + elsif project_name_list.count == 1 and os_list.count == 1 then + pname = project_name_list[0] + os = os_list[0] + + check_build_project(pname,passwd,dist_name,req) + if not check_project_user_id(pname,dist_name,user_id) then + raise BuildServerException.new("ERR005"), "#{user_email} -> #{pname}" + end + new_job = create_new_job( pname, os, dist_name ) + if new_job.nil? then + raise BuildServerException.new("ERR006"), "\"#{pname}\" does not support #{os} in #{dist_name}" + else + new_job.user_id = user_id + end else - @log.info "Received Wrong REQ: #{line}" - raise "Invalid request format is used: #{line}" - end + raise BuildServerException.new("ERR006"), "Cannot find your project to build!" + end + + # check reverse build + if no_reverse then new_job.set_no_reverse end + + # create logger and set + if async then + new_job.create_logger( nil, verbose) + BuildCommServer.send(req,"Info: Added new job \"#{new_job.id}\" for #{new_job.os}!") + if not @parent_server.job_log_url.empty? then + BuildCommServer.send(req,"Info: * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log") + end + BuildCommServer.send(req,"Info: Above job(s) will be processed asynchronously!") + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + else + logger = new_job.create_logger( req, verbose) + logger.info( "Added new job \"#{new_job.id}\" for #{new_job.os}!", Log::LV_USER) + if not @parent_server.job_log_url.empty? then + logger.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER) + end + end + + # add to job queue + if new_job.is_rev_build_check_job() then + @parent_server.jobmgr.add_reverse_build_job( new_job ) + else + @parent_server.jobmgr.add_job( new_job ) + end end - # "RESOLVE" - def handle_cmd_resolve( line ,req) - tok = line.split(",").map { |x| x.strip } - if tok.count < 4 then - @log.info "Received Wrong REQ: #{line}" - raise "Invalid request format is used: #{line}" + def check_build_project(prj_name, passwd, dist_name, req) + # check project + prj = check_project_exist(prj_name, dist_name, req) + + # check passwd + check_project_password(prj, passwd, req) + + # check project type + if prj.type == "BINARY" then + raise BuildServerException.new("ERR010"), prj.type + end + end + + + # "RESOLVE" + def handle_cmd_resolve( line, req ) + @log.info "Received REQ: #{line}" + + begin + handle_cmd_resolve_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + @log.info "Handled REQ: #{line}" + end + + + def handle_cmd_resolve_internal( line ,req) + tok = line.split("|").map { |x| x.strip } + if tok.count < 3 then + raise BuildServerException.new("ERR001"), line end case tok[1] - # RESOLVE,GIT,repos,commit,os,url + # RESOLVE|GIT|project_name|passwd|os|async|dist_name|user_email|verbose when "GIT" - @log.info "Received RESOLVE GIT => #{tok[2]}" - - BuildCommServer.send_begin(req) - @parent_server.add_job( - GitBuildJob.new( tok[2], tok[3], tok[4], tok[5], [], @parent_server, nil, req, true)) - # RESOLVE,LOCAL,path,os,url - when "LOCAL" - @log.info "Received RESOLVE LOCAL => #{tok[2]}" - - BuildCommServer.send_begin(req) - @parent_server.add_job( - LocalBuildJob.new( tok[2], tok[3], tok[4], [], @parent_server, nil, req, true)) + + # parse + project_name=tok[2] + passwd=tok[3] + os=tok[4] + async = tok[5].eql? "YES" + dist_name = tok[6] + user_email = (not tok[7].nil? and not tok[7].empty?) ? tok[7].strip : "" + verbose = tok[8].eql? "YES" + if (dist_name.nil? or dist_name.empty?) then + dist_name = @parent_server.distmgr.get_default_distribution_name() + end + + # check distribution + check_distribution(dist_name, req) + + # check project + prj = check_project_exist(project_name, dist_name, req) + + # check passwd + check_project_password(prj, passwd, req) + + # check os + os_list = check_supported_os( [os] , req ) + os = os_list[0] + + # check user email + user_id = @parent_server.check_user_id_from_email( user_email ) + if user_id == -1 then + raise BuildServerException.new("ERR004"), user_email + end + + # check user accessable + if not check_project_user_id(project_name,dist_name,user_id) then + raise BuildServerException.new("ERR005"), "#{user_email} -> #{project_name}" + end + + # create new job + new_job = create_new_job( project_name, os, dist_name ) + if new_job.nil? then + raise BuildServerException.new("ERR006"), "Resolve job #{project_name} #{os}" + end + @log.info "Received a request for resolving this project : #{project_name}, #{os}" + + new_job.user_id = user_id + + # resolve + new_job.set_resolve_flag() + + # create logger and set + if async then + new_job.create_logger( nil, verbose) + BuildCommServer.send(req,"Info: Added new job \"#{new_job.id}\" for #{new_job.os}!") + if not @parent_server.job_log_url.empty? then + BuildCommServer.send(req,"Info: * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log") + end + BuildCommServer.send(req,"Info: Above job(s) will be processed asynchronously!") + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + else + logger = new_job.create_logger( req, verbose) + logger.info( "Added new job \"#{new_job.id}\" for #{new_job.os}!", Log::LV_USER) + if not @parent_server.job_log_url.empty? then + logger.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER) + end + end + + @parent_server.jobmgr.add_job( new_job ) else - @log.info "Received Wrong REQ: #{line}" - raise "Invalid request format is used: #{line}" - end + raise BuildServerException.new("ERR001"), line + end end # "QUERY" def handle_cmd_query( line, req ) - tok = line.split(",").map { |x| x.strip } - if tok.count < 2 then - @log.info "Received Wrong REQ: #{line}" - raise "Invalid request format is used: #{line}" + begin + handle_cmd_query_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) end - + end + + + def handle_cmd_query_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 2 then + raise BuildServerException.new("ERR001"), line + end + case tok[1] - # QUERY,JOB + + # QUERY, FTP + when "FTP" + if not @parent_server.ftp_addr.nil? then + BuildCommServer.send(req,"#{@parent_server.ftp_addr},#{@parent_server.ftp_username},#{@parent_server.ftp_passwd}") + else + BuildCommServer.send(req,"NONE,NONE,NONE") + end + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + + # QUERY,JOB when "JOB" #puts "Received QUERY JOB" - BuildCommServer.send_begin(req) - for job in @parent_server.working_jobs - BuildCommServer.send(req,"WORKING,#{job.id},#{job.pkginfo.packages[0].source}") + # gather all jobs to show + job_list = @parent_server.jobmgr.jobs + @parent_server.jobmgr.internal_jobs + @parent_server.jobmgr.reverse_build_jobs + + # send the status + job_list.each do |job| + status = job.status + if status == "REMOTE_WORKING" then status = "REMOTE" end + if job.cancel_state != "NONE" then status = "CANCEL" end + + case job.type + when "BUILD" + if status == "PENDING" then + if job.pending_ancestor.nil? then + ids = "/" + else + ids = job.pending_ancestor.id + end + BuildCommServer.send(req,"#{status}:#{ids},#{job.id},#{job.get_project().name},#{job.os} #{job.progress},#{job.get_distribution_name}") + else + BuildCommServer.send(req,"#{status},#{job.id},#{job.get_project().name},#{job.os} #{job.progress},#{job.get_distribution_name}") + end + when "REGISTER" + if job.pkg_type == "BINARY" and not job.get_project().nil? then + BuildCommServer.send(req,"#{status},#{job.id},#{job.get_project().name},#{job.os} #{job.progress},#{job.get_distribution_name}") + else + BuildCommServer.send(req,"#{status},#{job.id},#{job.pkg_name},#{job.get_distribution_name}") + end + when "MULTIBUILD" + BuildCommServer.send(req,"#{status},#{job.id},MULTI-BUILD : #{job.get_sub_jobs().map{|x| x.id}.join(" ")},#{job.get_distribution_name}") + end end - for job in @parent_server.waiting_jobs - BuildCommServer.send(req,"WAITING,#{job.id},#{job.pkginfo.packages[0].source}") + + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + + # QUERY,SYSTEM + when "SYSTEM" + #puts "Received QUERY SYSTEM" + + BuildCommServer.send(req,"#{@parent_server.host_os},#{@parent_server.jobmgr.max_working_jobs}") + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + when "PROJECT" + # print GIT projects + sorted_list = @parent_server.prjmgr.get_all_projects_summary().sort { |x,y| x[:name] <=> y[:name] } + sorted_list.select{|x| x[:ptype] == "GIT"}.each do |prj| + BuildCommServer.send(req,"G,#{prj[:name]},#{prj[:dist_name]}") + end + # print BINARY projects + sorted_list.select{|x| x[:ptype] == "BINARY"}.each do |prj| + BuildCommServer.send(req,"B,#{prj[:name]},#{prj[:dist_name]}") end - for job in @parent_server.remote_jobs - BuildCommServer.send(req,"REMOTE ,#{job.id},#{job.pkginfo.packages[0].source}") + # print REMOTE project + sorted_list.select{|x| x[:ptype] == "REMOTE"}.each do |prj| + BuildCommServer.send(req,"R,#{prj[:name]},#{prj[:dist_name]}") end BuildCommServer.send_end(req) BuildCommServer.disconnect(req) - # QUERY,SYSTEM - when "SYSTEM" - #puts "Received QUERY SYSTEM" + when "OS" + # print GIT projects + @parent_server.supported_os_list.each do |os_name| + BuildCommServer.send(req,"#{os_name}") + end + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + + when "FRIEND" + # print GIT projects + @parent_server.remote_servers.each do |server| + BuildCommServer.send(req,"#{server.status},#{server.host_os},#{server.waiting_job_count},#{server.working_job_count},#{server.max_working_jobs},#{server.get_file_transfer_cnt}") + end + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + + else + raise BuildServerException.new("ERR001"), line + end + end + + + # "CANCEL" + def handle_cmd_cancel( line, req ) + @log.info "Received REQ: #{line}" + + begin + handle_cmd_cancel_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + @log.info "Handled REQ: #{line}" + end + + + def handle_cmd_cancel_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 2 then + raise BuildServerException.new("ERR001"), line + end + cancel_job = nil + + # check user email + user_id = @parent_server.check_user_id_from_email( tok[3] ) + if user_id == -1 then + raise BuildServerException.new("ERR004"), tok[3] + end + + #CANCEL, JOB + (@parent_server.jobmgr.jobs + @parent_server.jobmgr.internal_jobs + @parent_server.jobmgr.reverse_build_jobs).each do |j| + if "#{j.id}" == "#{tok[1]}" then + cancel_job = j + break + end + end + + if cancel_job.nil? then + raise BuildServerException.new("ERR014"), "Job #{tok[1]} not found." + else + if cancel_job.cancel_state == "NONE" then + # check passwd + if not @parent_server.jobmgr.is_user_accessable(cancel_job,user_id) then + raise BuildServerException.new("ERR014"), "Access denied #{tok[3]}" + end + if cancel_job.type == "MULTIBUILD" then + cancel_job.get_sub_jobs().select{|x| x.cancel_state == "NONE" }.each do |sub| + check_project_password( sub.get_project, tok[2], req) + end + + BuildCommServer.send(req, "\"#{cancel_job.id}, #{cancel_job.get_sub_jobs().map{|x| x.id}.join(", ")}\" will be canceled") + cancel_job.cancel_state = "INIT" + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + else + prj = cancel_job.get_project() + if not prj.nil? then + check_project_password( prj, tok[2], req) + + BuildCommServer.send(req, "\"#{cancel_job.id}\" will be canceled") + cancel_job.cancel_state = "INIT" + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + else + raise BuildServerException.new("ERR014"), "No project infomation" + end + end + else + raise BuildServerException.new("ERR014"), "Job already canceled." + end + end + end + + + # "STOP" + def handle_cmd_stop( line, req ) + @log.info "Received REQ: #{line}" + + begin + handle_cmd_stop_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + @log.info "Handled REQ: #{line}" + end + + + def handle_cmd_stop_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 2 then + raise BuildServerException.new("ERR001"), line + end + + if tok[1] != @parent_server.password then + raise BuildServerException.new("ERR015"), "" + else + BuildCommServer.send(req,"Server will be down!") + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + if tok[1] == @parent_server.password then + @parent_server.finish = true + end + end + - BuildCommServer.send_begin(req) - BuildCommServer.send(req,"#{@parent_server.host_os},#{@parent_server.max_working_jobs}") + # "UPGRADE" + def handle_cmd_upgrade( line, req ) + @log.info "Received REQ: #{line}" + + begin + handle_cmd_upgrade_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + @log.info "Handled REQ: #{line}" + end + + + def handle_cmd_upgrade_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 2 then + raise BuildServerException.new("ERR001"), line + end + + if tok[1] != @parent_server.password then + raise BuildServerException.new("ERR015"), "" + else + BuildCommServer.send(req,"Server will be upgraded!") BuildCommServer.send_end(req) BuildCommServer.disconnect(req) + end + if tok[1] == @parent_server.password then + @parent_server.finish = true + @parent_server.upgrade = true + end + end + + + # "FULLBUILD" + def handle_cmd_fullbuild( line, req ) + @log.info "Received REQ: #{line}" + + begin + handle_cmd_fullbuild_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + @log.info "Handled REQ: #{line}" + end + + + def handle_cmd_fullbuild_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 2 then + raise BuildServerException.new("ERR001"), line + end + + server_passwd = tok[1] + dist_name = tok[2] + if (dist_name.nil? or dist_name.empty?) then + dist_name = @parent_server.distmgr.get_default_distribution_name() + end + + # check distribution + check_distribution(dist_name, req, true) + + # check server password + if server_passwd != @parent_server.password then + raise BuildServerException.new("ERR015"), "" + end + + # create full build job + new_job = @parent_server.prjmgr.create_new_full_build_job(dist_name) + + # set logger + new_job.create_logger( req ) + + # add to job + @parent_server.jobmgr.add_job( new_job ) + end + + + # "REGISTER" + def handle_cmd_register( line, req ) + @log.info "Received REQ: #{line}" + + begin + handle_cmd_register_internal( line, req ) + rescue BuildServerException => e + @log.error(e.message) + BuildCommServer.send(req, e.err_message()) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + @log.info "Handled REQ: #{line}" + end + + + def handle_cmd_register_internal( line, req ) + tok = line.split("|").map { |x| x.strip } + if tok.count < 4 then + raise BuildServerException.new("ERR001"), line + end + + type = tok[1] + + case type + # REGISTER|BINARY-LOCAL|local_path|passwd|dist_name + # REGISTER|SOURCE-LOCAL|local_path|passwd|dist_name + when "BINARY-LOCAL", "SOURCE-LOCAL" + file_path = tok[2] + dist_name = tok[4] + if (dist_name.nil? or dist_name.empty?) then + dist_name = @parent_server.distmgr.get_default_distribution_name() + end + + # check distribution + check_distribution(dist_name, req) + + new_job = @parent_server.jobmgr.create_new_register_job( file_path, dist_name ) + new_job.create_logger( req ) + + # add + @parent_server.jobmgr.add_job( new_job ) + + # REGISTER|BINARY|filename|passwd|dock|dist_name|user_email|no_reverse + when "BINARY" + # parse + filename = tok[2] + passwd = tok[3] + dock = (tok[4].nil? or tok[4].empty?) ? "0" : tok[4].strip + dist_name = tok[5] + user_email = (tok[7].nil? or tok[7].empty?) ? "" : tok[6].strip + no_reverse = tok[7].eql? "YES" + + if (dist_name.nil? or dist_name.empty?) then + dist_name = @parent_server.distmgr.get_default_distribution_name() + end + + # check distribution + check_distribution(dist_name, req) + + # check project + prj = check_project_for_package_file_name(filename, dist_name, req) + + # check user email + user_id = @parent_server.check_user_id_from_email( user_email ) + if user_id == -1 then + raise BuildServerException.new("ERR004"), user_email + end + + if not check_project_pkg_name_user_id(filename, dist_name, user_id) then + raise BuildServerException.new("ERR005"), "#{user_email} -> #{prj.name}" + end + + # check passwd + check_project_password(prj, passwd, req) + + # create new job + @log.info "Received a request for uploading binaries : #{filename}" + new_job = create_new_upload_job( prj.name, filename, dock, dist_name, req ) + if new_job.nil? then + raise BuildServerException.new("ERR006"), "Register-job #{filename}, #{prj.name}, #{dist_name}" + end + + new_job.user_id = user_id + + # check reverse build + if no_reverse then new_job.set_no_reverse end + + # create logger and set + logger = new_job.create_logger(req) + + # notify that job has been received + logger.info( "Added new job \"#{new_job.id}\" for #{new_job.os}!", Log::LV_USER) + if not @parent_server.job_log_url.empty? then + logger.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER) + end + + # add + @parent_server.jobmgr.add_job( new_job ) else - @log.info "Received Wrong REQ: #{line}" - raise "Invalid request format is used: #{line}" + raise BuildServerException.new("ERR001"), line + end + + end + + + # "UPLOAD" + def handle_cmd_upload( line, req ) + @log.info "Received File transfer REQ : #{line}" + + tok = line.split("|").map { |x| x.strip } + dock_num = (tok[1].nil? or tok[1].empty?) ? "0" : tok[1].strip + + incoming_dir = "#{@parent_server.transport_path}/#{dock_num}" + if not File.exist? incoming_dir then FileUtils.mkdir_p incoming_dir end + @comm_server.receive_file( req, incoming_dir ) + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + + # "DOWNLOAD" + # format = DOWNLOAD|dock_num|file_name + def handle_cmd_download( line, req ) + @log.info "Received File transfer REQ : #{line}" + tok = line.split("|").map { |x| x.strip } + dock_num = (tok[1].nil? or tok[1].empty?) ? "0" : tok[1].strip + file_name = tok[2] + + @log.info "Received a request for download file : #{file_name}" + outgoing_dir = "#{@parent_server.transport_path}/#{dock_num}" + @log.info "Sending requested file...: #{file_name}" + @comm_server.send_file(req, "#{outgoing_dir}/#{file_name}") + # remove file if "dock" defined + if dock_num != "0" and File.exist? "#{outgoing_dir}/#{file_name}" then + @log.info "Removing requested file...: #{file_name}" + FileUtils.rm_rf "#{outgoing_dir}/#{file_name}" + if Utils.directory_emtpy?(outgoing_dir) then + FileUtils.rm_rf "#{outgoing_dir}" + end end + + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end + + + private + def check_project_user_id(project_name, dist_name, user_id) + return @parent_server.prjmgr.get_project_accessable(project_name, dist_name, user_id) + end + + private + def check_project_exist(project_name, dist_name, req) + prj = @parent_server.prjmgr.get_project(project_name, dist_name) + if prj.nil? then + raise BuildServerException.new("ERR009"), "#{project_name} on #{dist_name}" + end + + return prj + end + + private + def check_project_pkg_name_user_id(file_name, dist_name, user_id) + # get package name + new_name = file_name.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + pkg_name = new_name.split(",")[0] + return @parent_server.prjmgr.get_project_pkg_name_accessable(pkg_name, dist_name, user_id) end + private + def check_project_for_package_file_name(filename, dist_name, req) + # get package name + new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + pkg_name = new_name.split(",")[0] + + prj = @parent_server.prjmgr.get_project_from_package_name(pkg_name, dist_name) + if prj.nil? then + raise BuildServerException.new("ERR013"), "#{pkg_name} #{dist_name}" + end + + return prj + end + + + private + def check_project_password(prj, passwd, req) + + if prj.is_passwd_set? then + if passwd.nil? or passwd.empty? then + raise BuildServerException.new("ERR011"), "Use -w option to input your project password" + end + + if not prj.passwd_match?(passwd) then + raise BuildServerException.new("ERR012"), "" + end + end + end + + + private + def check_distribution(dist_name, req, only_exist = false) + dist = @parent_server.distmgr.get_distribution(dist_name) + if dist.nil? then + raise BuildServerException.new("ERR002"), dist_name + elsif dist.status != "OPEN" and not only_exist then + raise BuildServerException.new("ERR008"), dist_name + end + end + + + private + def check_supported_os(os_list, req) + + # check if supported os list contain at least one OS + if @parent_server.supported_os_list.empty? then + raise BuildServerException.new("ERR007"), "" + end + + result = [] + os_list.each do |os| + if os == "all" or os == "*" then + result = result + @parent_server.supported_os_list + + elsif os == "default" then + os = @parent_server.supported_os_list[0] + result.push os + @log.info "The default OS \"#{os}\" is used as target OS" + + elsif os.include? "*" then + reg_os = os.gsub("*","[a-zA-Z0-9.]*") + @parent_server.supported_os_list.each do |svr_os| + matches = svr_os.match("#{reg_os}") + if not matches.nil? and matches.size == 1 and + matches[0] == svr_os then + result.push svr_os + end + end + elsif @parent_server.supported_os_list.include?(os) then + result.push os + else + msgs = "#{os}\n\tSupported OS list.\n" + @parent_server.supported_os_list.each do |os_name| + msgs += "\t * #{os_name}\n" + end + raise BuildServerException.new("ERR003"),msgs + end + end + + result.uniq! + if result.empty? then + raise BuildServerException.new("ERR003"), "There is no OS name matched." + end + + return result + end + + + private + def create_new_job( project_name, os, dist_name ) + return @parent_server.prjmgr.create_new_job(project_name, os, dist_name) + end + + + private + def create_new_upload_job( project_name, filename, dock, dist_name, req) + + return @parent_server.prjmgr.get_project(project_name, dist_name).create_new_job(filename, dock) + end + + + private + def create_new_internal_job( git_repos, os, git_commit, pkg_files, dock_num, dist_name ) + prj = @parent_server.prjmgr.get_git_project( git_repos, dist_name ) + if prj.nil? then + prj = @parent_server.prjmgr.create_unnamed_git_project( git_repos, dist_name ) + end + new_job = prj.create_new_job(os) + new_job.set_internal_job( dock_num ) + new_job.git_commit = git_commit + incoming_dir = "#{@parent_server.transport_path}/#{dock_num}" + pkg_files.each do |file| + new_job.add_external_package( file ) + end + + return new_job + end end diff --git a/src/builder/Builder.rb b/src/builder/Builder.rb index a9e672c..386cb94 100644 --- a/src/builder/Builder.rb +++ b/src/builder/Builder.rb @@ -1,5 +1,5 @@ =begin - + Builder.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -36,22 +36,29 @@ require "log" class Builder private_class_method :new - attr_accessor :id, :pkgserver_url, :log + attr_accessor :id, :pkgserver_url, :log, :buildroot_dir, :cache_dir CONFIG_ROOT = Utils::HOME + "/.build_tools/builder" @@instance_map = {} # initialize - def initialize (id, pkgserver_url, log_path) + def initialize (id, pkgserver_url, log_path, buildroot_dir, cache_dir) @id = id @pkgserver_url = pkgserver_url @host_os = Utils::HOST_OS - @log = Log.new(log_path) + @buildroot_dir = buildroot_dir + @cache_dir = cache_dir + @job = nil + if not log_path.nil? then + @log = Log.new(log_path) + else + @log = DummyLog.new + end end - + # create - def self.create (id, pkgserver_url, log_path) + def self.create (id, pkgserver_url, log_path, buildroot_dir, cache_dir) # check builder config root check_builder_config_root @@ -61,8 +68,24 @@ class Builder FileUtils.rm_rf "#{CONFIG_ROOT}/#{id}" end + # create buildroot if not set + if buildroot_dir.nil? then + buildroot_dir = "#{CONFIG_ROOT}/#{id}/buildroot" + if not File.exist? buildroot_dir then + FileUtils.mkdir_p buildroot_dir + end + end + + # create cachedir if not set + if cache_dir.nil? then + cache_dir = "#{CONFIG_ROOT}/#{id}/build_cache" + if not File.exist? cache_dir then + FileUtils.mkdir_p cache_dir + end + end + # create new instance and return it - @@instance_map[id] = new( id, pkgserver_url, log_path ) + @@instance_map[id] = new( id, pkgserver_url, log_path, buildroot_dir, cache_dir ) # write config write_builder_config( @@instance_map[id] ) @@ -83,16 +106,28 @@ class Builder end + def self.exist?( id ) + # check builder config root + check_builder_config_root + + # check id + if File.exist? "#{CONFIG_ROOT}/#{id}" then + return true + else + return false + end + end + # get def self.get( id ) # check instance first if not @@instance_map[id] == nil - return @@instance_map[id] + return @@instance_map[id] end - # check builder config - if not File.exist? "#{CONFIG_ROOT}/#{id}/builder.cfg" + # check builder config + if not File.exist? "#{CONFIG_ROOT}/#{id}/builder.cfg" raise RuntimeError, "The builder \"#{id}\" does not exist." end @@ -106,68 +141,109 @@ class Builder # clean def clean( src_path ) - build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot" + return clean_project_directory( src_path, nil ) + end - # create pkginfo - pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest") - # make clean - for pkg in pkginfo.packages - FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.linux" - FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.windows" - FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.darwin" - end - env_def = - "SRCDIR=\"#{src_path}\" " - build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} clean" - if not Utils.execute_shell_with_log( build_command, @log ) - @log.error( "Failed on clean script", Log::LV_USER ) - return false - end + # build_job + def build_job( job, clean, local_pkgs, is_local_build ) + # set job + @job = job + old_log = @log + @log = job.log - return true + # build + ret = build(job.source_path, job.os, clean, local_pkgs, is_local_build) + + # reset job + @job = nil + @log = old_log + + # return + return ret end # build - def build( src_path, os, clean, reverse_dep_check, pending_pkg_dir_list, ignore_rev_dep_build_list ) + def build( src_path, os, clean, local_pkgs, is_local_build ) # create pkginfo - pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest") + if not File.exist? "#{src_path}/package/pkginfo.manifest" then + @log.error( "The \"package/pkginfo.manifest\" file does not exist!", Log::LV_USER) + return false + end - # check there are packages which can be built - if not pkginfo.package_exist?(os, Utils::HOST_OS ) then - @log.error( "There are no packages which can be built on this host OS: #{Utils::HOST_OS}") - @log.error( " * Check \"Build-host-os\" in pkginfo.manifest" ) + # read pkginfo + begin + pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest") + rescue => e + @log.error( e.message, Log::LV_USER) return false end - # set build root - if clean then - build_root_dir = "#{CONFIG_ROOT}/#{@id}/temp_root" - else - build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot" + # set default build os + build_host_os = @host_os + + # check there are packages which can be built + if not pkginfo.package_exist?(os, build_host_os ) then + if is_local_build and File.exist? "#{src_path}/package/pkginfo.manifest.local" then + begin + pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest.local") + rescue => e + @log.error( e.message, Log::LV_USER) + return false + end + if not pkginfo.package_exist?(os, build_host_os ) then + + @log.error( "This project does not support a build on this host OS: #{build_host_os}") + @log.error( " * Check \"Build-host-os\" in pkginfo.manifest or pkginfo.manifest.local" ) + + return false + end + else + @log.error( "This project does not support a build on this host OS: #{build_host_os}") + @log.error( " * Check \"Build-host-os\" in pkginfo.manifest" ) + + return false + end + end + + #set up change log + change_log = {} + begin + change_log = Parser.read_changelog "#{src_path}/package/changelog" if File.exist? "#{src_path}/package/changelog" + rescue => e + @log.error( e.message, Log::LV_USER) + return false end - FileUtils.mkdir_p build_root_dir + if not change_log.empty? and pkginfo.packages[0].change_log.empty? then + pkginfo.packages.each {|pkg| pkg.change_log = change_log} + end - local_pkg_list = [] - pending_pkg_dir_list.each do |dir| - local_pkg_list += Dir.entries(dir).select{|e| e =~ /\.zip$/}.map{|p| dir + "/" + p} - end + # set build root + build_root_dir = @buildroot_dir + if not File.exist? build_root_dir then + FileUtils.mkdir_p build_root_dir + end # create client @log.info( "Downloding client is initializing...", Log::LV_USER) - cl = Client.new(@pkgserver_url, build_root_dir, @log) - if clean then + cl = Client.new(@pkgserver_url, build_root_dir, @log) + if clean then cl.clean(true) end - cl.update + + # get local repository path list + repos_paths = [] + local_pkgs.each do |path| + repos_paths.push File.dirname(path) + end + repos_paths.uniq! # install build dependencies - package_overwrite_list = [] @log.info( "Installing dependent packages...", Log::LV_USER) - pkginfo.get_build_dependencies( os, @host_os ).each do |dep| + pkginfo.get_build_dependencies( os ).each do |dep| if dep.target_os_list.count != 0 then dep_target_os = dep.target_os_list[0] else @@ -175,75 +251,54 @@ class Builder end @log.info( " * #{dep.package_name}", Log::LV_USER) - # get local dependent package - pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$") - package_overwrite_list += local_pkg_list.select{|l| l =~ pkgexp} + # get local dependent package + pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$") + local_dep_pkgs = local_pkgs.select{|l| l =~ pkgexp} - if not cl.install(dep.package_name, dep_target_os, true, false) then - @log.error( "Installing \"#{dep.package_name}\" failed!", Log::LV_USER) - return false + # install package from remote package server + if local_dep_pkgs.empty? then + if not cl.install(dep.package_name, dep_target_os, true, false) then + @log.error( "Installing \"#{dep.package_name}\" failed!", Log::LV_USER) + return false + end + else + local_dep_pkgs.each do |l| + @log.info( "Installing local package...#{l}", Log::LV_USER) + if not File.exist? l then + @log.error( "File not found!: #{l}", Log::LV_USER ) + end + cl.install_local_pkg(l,true,false, repos_paths) + end end end - # overwrite local dependent packages - package_overwrite_list.each do |l| - cl.install_local_pkg(l,false) - end - @log.info( "Downloading dependent source packages...", Log::LV_USER) - pkginfo.get_source_dependencies(os,@host_os).each do |dep| - @log.info( " * #{dep.package_name}", Log::LV_USER) - - if cl.download_dep_source(dep.package_name).nil? then - @log.error( "Downloading \"#{dep.package_name}\" failed!", Log::LV_USER) - return false - end - end - - # make clean - @log.info( "Make clean...", Log::LV_USER) - for pkg in pkginfo.packages - FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.linux" - FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.windows" - FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.darwin" - end - - # convert path if windows - if Utils::HOST_OS == "windows" then - build_root_dir = Utils.get_unix_path( build_root_dir ) + src_archive_list = [] + pkginfo.get_source_dependencies(os,build_host_os).each do |dep| + src_archive_list.push dep.package_name end - env_def = - "BUILD_TARGET_OS=#{os} \ - SRCDIR=\"#{src_path}\" \ - ROOTDIR=\"#{build_root_dir}\" " - build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} clean" - - if not Utils.execute_shell_with_log( build_command, @log ) - @log.error( "Failed on clean script", Log::LV_USER) - return false + src_archive_list.uniq! + src_archive_list.each do |archive_name| + @log.info( " * #{archive_name}", Log::LV_USER) + if cl.download_dep_source(archive_name).nil? then + @log.error( "Downloading \"#{archive_name}\" failed!", Log::LV_USER) + return false + end end - # make source package - @log.info( "Make source package...", Log::LV_USER) - build_command = "cd \"#{src_path}\";tar czf #{pkginfo.packages[0].source}_#{pkginfo.packages[0].version}.tar.gz --exclude=.git *" - if not Utils.execute_shell_with_log( build_command, @log ) - @log.error( "Failed on tar script", Log::LV_USER) + # make clean + @log.info( "Make clean...", Log::LV_USER) + if not clean_project_directory( src_path, os ) then return false end - # execute build script @log.info( "Make build...", Log::LV_USER) - build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} build" - if not Utils.execute_shell_with_log( build_command, @log ) - @log.error( "Failed on build script", Log::LV_USER) + if not execute_build_command("build", src_path, build_root_dir, os, pkginfo.get_version) then return false end - # execute install script @log.info( "Make install...", Log::LV_USER) - build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} install" - if not Utils.execute_shell_with_log( build_command, @log ) - @log.error( "Failed on build script", Log::LV_USER) + if not execute_build_command("install", src_path, build_root_dir, os, pkginfo.get_version) then return false end @@ -256,37 +311,12 @@ class Builder # zip @log.info( "Zipping...", Log::LV_USER) - make_zip(pkginfo,os,src_path) - - # check reverse dependecy if needed - if reverse_dep_check then - if not check_reverse_build_dependency_fail_list(src_path, os, cl, true, ignore_rev_dep_build_list).empty? then - return false - end + if not make_zip(pkginfo,os,src_path) then + @log.error( "Creating packages failed!", Log::LV_USER) + return false end - return true - end - def build_resolve(src_path, os, pending_pkg_dir_list, ignore_rev_dep_build_list) - # clean build - if not build(src_path, os, true, false, pending_pkg_dir_list, ignore_rev_dep_build_list) then - return nil - end - # init client - build_root_dir = "#{CONFIG_ROOT}/#{@id}/temp_root" - cl = Client.new(@pkgserver_url, build_root_dir, @log) - # rev build - return check_reverse_build_dependency_fail_list(src_path, os, cl, false, ignore_rev_dep_build_list ) - end - - - # reset - def reset() - build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot" - temp_dir = cl.location - cl.location = build_root_dir - cl.clean(true) - cl.location = temp_dir + return true end @@ -307,15 +337,17 @@ class Builder def self.write_builder_config( obj ) # create config folder builder_dir = "#{CONFIG_ROOT}/#{obj.id}" - FileUtils.mkdir_p( "#{builder_dir}" ) + if not File.exist? builder_dir then + FileUtils.mkdir_p( "#{builder_dir}" ) + end # write configuration File.open( "#{builder_dir}/builder.cfg", "w" ) do |f| f.puts "ID=#{obj.id}" f.puts "PSERVER_URL=#{obj.pkgserver_url}" f.puts "LOG-PATH=#{obj.log.path}" + f.puts "CACHE-DIR=#{obj.cache_dir}" end - puts "#{builder_dir}/builder.cfg" end @@ -325,166 +357,169 @@ class Builder # read configuration builder_dir = "#{CONFIG_ROOT}/#{id}" - log_path = nil + log_path = nil + cache_dir = "#{CONFIG_ROOT}/#{id}/build_cache" + buildroot_dir = "#{CONFIG_ROOT}/#{id}/buildroot" File.open( "#{builder_dir}/builder.cfg", "r" ) do |f| f.each_line do |l| if l.start_with?("PSERVER_URL=") - pkgserver_url = l.split("=")[1].strip - elsif l.start_with?("LOG-PATH=") - log_path = l.split("=")[1].strip - log_path = nil if log_path == "STDOUT" + pkgserver_url = l.split("=")[1].strip + elsif l.start_with?("LOG-PATH=") + log_path = l.split("=")[1].strip + log_path = nil if log_path == "STDOUT" + elsif l.start_with?("CACHE-DIR=") + cache_dir = l.split("=")[1].strip + elsif l.start_with?("BUILDROOT-DIR=") + buildroot_dir = l.split("=")[1].strip else - next - end + next + end end end - if log_path.empty? then log_path = nil end - # create object & return it - return new( id, pkgserver_url, log_path ) - end + if log_path.empty? then log_path = nil end - - # check reverse build dependency - def check_reverse_build_dependency_fail_list( parent_path, os, pkg_cl, immediately, ignore_rev_dep_build_list ) - @log.info( "Checking reverse build dependency ...", Log::LV_USER) - - reverse_fail_list = [] - - # install newly packages - for path in Dir.glob("*_*_#{os}.zip") - # install - pkg_cl.install_local_pkg( path, false ) - end - - # get reverse-dependent source-codes - pkginfo = PackageManifest.new("#{parent_path}/package/pkginfo.manifest") - pkg_list = [] - for pkg in pkginfo.packages - pkg_list = pkg_list + pkg_cl.get_reverse_build_dependent_packages(pkg.package_name, os) - @log.info( "Extract reverse build dependency #{pkg.package_name} ...", Log::LV_USER) - end - pkg_list -= ignore_rev_dep_build_list - pkg_list.uniq! - - # download sources - src_path_hash = {} - pkg_list.each do |pkg| - # download - src_path = pkg_cl.download_source(pkg, os) - @log.info( "Downloaded #{pkg} source package to #{src_path}", Log::LV_USER) - - if src_path_hash[src_path].nil? then - src_path_hash[src_path] = [pkg] - else - src_path_hash[src_path] += [pkg] - end - end - src_path_list = src_path_hash.keys - - # add jobs for building reverse-dependent - src_path_list.each do |path| - # extract source package to test path - @log.info( " * Extracting source ... #{path}", Log::LV_USER) - test_src_path = "#{parent_path}/tmp_build" - FileUtils.mkdir_p test_src_path - Utils.execute_shell("cd \"#{test_src_path}\";tar xf #{path}") - - # build - @log.info( " * Building source ... ", Log::LV_USER) - result = build_test_with_pkg_client( pkg_cl, test_src_path, os, parent_path ) - FileUtils.rm_rf test_src_path - if not result then - reverse_fail_list += src_path_hash[path] - @log.error( "Build \"#{src_path_hash[path].join(", ")}\" test failed", Log::LV_USER) - if immediately then - return reverse_fail_list - end - end - end - - return reverse_fail_list.uniq + # create object & return it + return new( id, pkgserver_url, log_path, buildroot_dir, cache_dir ) end - # build test - def build_test_with_pkg_client( pkg_cl, src_path, os, parent_path) + # execute build command + def execute_build_command( target, src_path, build_root_dir, os, version ) - local_pkg_list = [] - local_pkg_list += Dir.entries(parent_path).select{|e| e =~ /\.zip$/}.map{|p| parent_path + "/" + p} + # get category + os_category = Utils.get_os_category( os ) - # create pkginfo - pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest") + # convert directory format when windows + if Utils.is_windows_like_os( @host_os ) then + src_path2 = Utils.get_unix_path( src_path ) + else + src_path2 = src_path + end - # install build dependencies - package_overwrite_list = [] - pkginfo.get_build_dependencies(os,@host_os).each do |dep| - if dep.target_os_list.count != 0 then - dep_target_os = dep.target_os_list[0] - else - dep_target_os = os + env_def = + "BUILD_TARGET_OS=#{os} \ +TARGET_OS=#{os} \ +TARGET_OS_CATEGORY=#{os_category} \ +SRCDIR=\"#{src_path2}\" \ +ROOTDIR=\"#{build_root_dir}\" \ +VERSION=\"#{version}\" " + + # check script file + script_file = "#{src_path}/package/build.#{@host_os}" + if not File.exist? script_file then + if Utils.is_linux_like_os( @host_os ) then + script_file = "#{src_path}/package/build.linux" + elsif Utils.is_windows_like_os( @host_os ) then + script_file = "#{src_path}/package/build.windows" + elsif Utils.is_macos_like_os( @host_os ) then + script_file = "#{src_path}/package/build.macos" + end + # check old script file + if not File.exist? script_file then + @log.error( "The script file not found!: \"package/build.#{@host_os}\"", Log::LV_USER) + return false end + end - # get local dependent package - pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$") - package_overwrite_list += local_pkg_list.select{|l| l =~ pkgexp} + # read build script + # this will ignore last lines without block + contents = [] + File.open( script_file, "r" ) do |f| + lines = [] + f.each_line do |l| + lines.push l + if l.start_with? "}" then + contents = contents + lines + lines = [] + end + end + end - pkg_cl.install(dep.package_name, dep_target_os, true, false) - end + # generate shell script + File.open( "#{src_path}/.build.sh", "w" ) do |f| + f.puts "#!/bin/sh -xe" + contents.each do |l| + f.puts l + end - # overwrite local dependent packages - package_overwrite_list.each do |l| - @log.info( "Package overwrite ..#{l}", Log::LV_USER) - pkg_cl.install_local_pkg(l,false) - end + case target + when "clean" + f.puts " " + when "build" + f.puts " " + when "build_cache" + f.puts "CACHEDIR=${PKG_CACHE_DIR}/$(cache_key)" + when "save_cache" + f.puts "rm -rf ${PKG_CACHE_DIR}/*" + f.puts "CACHEDIR=${PKG_CACHE_DIR}/$(cache_key)" + f.puts "mkdir -p ${CACHEDIR}" + when "install" + f.puts " " + else + @log.warn( "Wrong build-target is used: \"#{target}\"", Log::LV_USER) + return false + end + f.puts "#{target}" + f.puts "echo \"success\"" + end + Utils.execute_shell( "chmod +x #{src_path}/.build.sh" ) + build_command = "cd \"#{src_path}\";" + env_def + "./.build.sh" - # source download - pkginfo.get_source_dependencies(os,@host_os).each do |dep| - pkg_cl.download_dep_source(dep.package_name) + # execute script + status = nil + if not @job.nil? then + pid, status = @job.execute_command( build_command ) + else + pid, status = Utils.execute_shell_with_log( build_command, @log.path ) end - # execute build script - build_root_dir = pkg_cl.location - env_def = - "BUILD_TARGET_OS=#{os} \ - SRCDIR=\"#{src_path}\" \ - ROOTDIR=\"#{build_root_dir}\" " - build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} build" - if not Utils.execute_shell_with_log( build_command, @log ) then - @log.error( "Failed on build script", Log::LV_USER) + if not status.nil? and status.exitstatus != 0 then + @log.error( "Failed on build script: \"#{target}\"", Log::LV_USER) return false else + Utils.execute_shell( "rm -rf #{src_path}/.build.sh" ) return true end - end - # write pkginfo.manifest and install/remove script + # write pkginfo.manifest def write_pkginfo_files(pkginfo,os,src_path) - for pkg in pkginfo.packages + # get category + os_category = Utils.get_os_category( os ) + + pkginfo.packages.each do |pkg| # skip if not support the target os - if not pkg.os.include? os + if not pkg.os_list.include? os next end - # install script files - copy_post_install_script(pkg,os,src_path); - copy_post_remove_script(pkg,os,src_path); + # install/remove script files + if not copy_post_install_script(pkg,os,src_path) then return false end + if not copy_post_remove_script(pkg,os,src_path) then return false end # write manifest file install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}" - + # if there is no intall directory, error if not File.exist? install_dir then - @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER) - @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER) - return false + install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" + + if not File.exist? install_dir then + @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER) + @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER) + @log.error( "Host OS name : #{@host_os}", Log::LV_USER) + @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER) + return false + end end - - # write pkginfo.manifest + + # write pkginfo.manifest File.open("#{install_dir}/pkginfo.manifest", "w") do |f| - pkg.print_to_file_with_os( f, os ) + f.puts pkg + f.puts "" + f.puts pkg.change_log_string end end @@ -494,74 +529,219 @@ class Builder # copy post-install script def copy_post_install_script(pkg,os,src_path) - + tar = nil + src = nil - if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{os}" - src = "#{src_path}/package/#{pkg.package_name}.install.#{os}" - else - src = nil + # get category + os_category_list = [] + pkg.os_list.each do |cos| + os_category_list.push Utils.get_os_category(cos) + end + + # check compatable os + (pkg.os_list + os_category_list).uniq.each do |cos| + if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{cos}" then + if src.nil? then + src = "#{src_path}/package/#{pkg.package_name}.install.#{cos}" + else + @log.error( "compatable package can have only one install script\n but you have another availabe install scripts", Log::LV_USER) + @log.error( " * package/#{File.basename src}", Log::LV_USER) + @log.error( " * package/#{pkg.package_name}.install.#{cos}", Log::LV_USER) + return false + end + end + end + + install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}" + + # if there is no intall directory, error + if not File.exist? install_dir then + os_category = Utils.get_os_category( os ) + install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" + + if not File.exist? install_dir then + @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER) + @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER) + @log.error( "Host OS name : #{@host_os}", Log::LV_USER) + @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER) + return false + end end if not src.nil? then - if os == "linux" or os == "darwin" then - tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/install.sh" - elsif os == "windows" then - tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/install.BAT" + if Utils.is_unix_like_os( os ) then + tar = "#{install_dir}/install.sh" + elsif Utils.is_windows_like_os( os) then + tar = "#{install_dir}/install.BAT" else puts "Unknown OS: #{os} " - return + return true end FileUtils.cp(src, tar) - end - - return + end + + return true end # copy post-remove script def copy_post_remove_script(pkg,os,src_path) - + tar = nil + src = nil - if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{os}" - src = "#{src_path}/package/#{pkg.package_name}.remove.#{os}" - else - src = nil + # get category + os_category_list = [] + pkg.os_list.each do |cos| + os_category_list.push Utils.get_os_category(cos) + end + + # check compatable os + (pkg.os_list + os_category_list).uniq.each do |cos| + if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{cos}" then + if src.nil? then + src = "#{src_path}/package/#{pkg.package_name}.remove.#{cos}" + else + @log.error( "compatable package can have only one remove script but you have another availabe remove scripts", Log::LV_USER) + @log.error( " * package/#{File.basename src}", Log::LV_USER) + @log.error( " * package/#{pkg.package_name}.remove.#{cos}", Log::LV_USER) + return false + end + end + end + + install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}" + + # if there is no intall directory, error + if not File.exist? install_dir then + os_category = Utils.get_os_category( os ) + install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" + + if not File.exist? install_dir then + @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER) + @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER) + @log.error( "Host OS name : #{@host_os}", Log::LV_USER) + @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER) + return false + end end if not src.nil? - puts "------> #{src}" - if os == "linux" or os == "darwin" then - tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/remove.sh" - puts "-0--\==> #{tar}" - elsif os == "windows" then - tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/remove.BAT" + if Utils.is_unix_like_os( os ) then + tar = "#{install_dir}/remove.sh" + elsif Utils.is_windows_like_os( os) then + tar = "#{install_dir}/remove.BAT" else puts "Unknown OS: #{os} " - return + return true end FileUtils.cp(src, tar) - end + end + return true end # create package file def make_zip(pkginfo,os,src_path) - for pkg in pkginfo.packages + # get category + os_category = Utils.get_os_category( os ) + + pkginfo.packages.each do |pkg| # skip if not support the target os - if not pkg.os.include? os + if not pkg.os_list.include? os next end # cd install dir install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}" - - # zip + if not File.exist? install_dir then + install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" + + if not File.exist? install_dir then + @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER) + @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER) + @log.error( "Host OS name : #{@host_os}", Log::LV_USER) + @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER) + return false + end + end + + # zip @log.info( "Creating package file ... #{pkg.package_name}_#{pkg.version}_#{os}.zip", Log::LV_USER) - Utils.execute_shell("cd \"#{install_dir}\"; zip -r -y #{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip *") + cmd = "cd \"#{install_dir}\"; zip -r -y #{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip *" + @log.info( cmd ) + if not @job.nil? then + @job.execute_command( cmd ) + else + Utils.execute_shell_with_log(cmd, @log.path) + end + + if not File.exist? "#{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip" then + return false + end end + return true + end + + + # clean the temporary directory for packaged + def clean_project_directory(src_path, target_os = nil) + + # if os is not set, use host os instead + if target_os.nil? then target_os = @host_os end + + # convert path if windows + if Utils.is_windows_like_os(@host_os) then + build_root_dir = Utils.get_unix_path( @buildroot_dir ) + else + build_root_dir = @buildroot_dir + end + + # create pkginfo + begin + pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest") + rescue => e + @log.error( e.message, Log::LV_USER) + return false + end + + # get category + # make clean + pkginfo.packages.each do |pkg| + os = pkg.os + os_category = Utils.get_os_category( os ) + + if File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}" then + FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}" + elsif File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" then + FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" + end + end + + # clean local-only package's directory + if File.exist? "#{src_path}/package/pkginfo.manifest.local" then + begin + pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest.local") + rescue => e + @log.error( e.message, Log::LV_USER) + return false + end + pkginfo.packages.each do |pkg| + os = pkg.os + os_category = Utils.get_os_category( os ) + + if File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}" then + FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}" + elsif File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" then + FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" + end + end + end + + # execute + return execute_build_command("clean", src_path, build_root_dir, target_os, pkginfo.get_version) end end diff --git a/src/builder/CleanOptionParser.rb b/src/builder/CleanOptionParser.rb index 31611fc..7a2646b 100644 --- a/src/builder/CleanOptionParser.rb +++ b/src/builder/CleanOptionParser.rb @@ -1,6 +1,6 @@ =begin - - CleanOptionParser.rb + + CleanOptionParser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -28,20 +28,30 @@ Contributors: require 'optparse' require 'logger' +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "utils" def parse() - #option parsing - option = {} - optparse = OptionParser.new do |opts| - opts.banner = "Usage: pkg-clean" - opts.on('-h','--help', 'display this information') do - puts opts - exit - end - end - - optparse.parse! - - return option -end + #option parsing + option = {} + optparse = OptionParser.new(nil, 32, ' '*8) do |opts| + opts.banner = "Clean the package service command-line tool." + "\n" \ + + "\n" + "Usage: pkg-clean [-h] [-v]" + "\n" \ + + "\n" + "Options:" + "\n" + + opts.on('-h','--help', 'display help') do + puts opts + exit + end + + opts.on('-v','--version', 'display version') do + puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version() + exit + end + end + + optparse.parse! + + return option +end diff --git a/src/builder/optionparser.rb b/src/builder/optionparser.rb index 05888f0..e8bab2c 100644 --- a/src/builder/optionparser.rb +++ b/src/builder/optionparser.rb @@ -1,5 +1,5 @@ =begin - + optionparser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -28,35 +28,53 @@ Contributors: require 'optparse' require 'logger' +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "utils" def parse() - #option parsing - option = {} - optparse = OptionParser.new do |opts| - opts.banner = "Usage: pkg-build -u -o -c -h" - opts.on('-u','--url ', 'remote package server url') do |url| - option[:url] = url - end - option[:os] = nil - opts.on('-o','--os ', 'operating system ') do |os| - option[:os] = os - end - option[:clean] = false - opts.on('-c','--clean', 'clean build') do - option[:clean] = true - end - option[:rev] = false - opts.on('-r','--rev', 'reverse build dependency check') do - option[:rev] = true - end - opts.on('-h','--help', 'display this information') do - puts opts - exit - end - end - - optparse.parse! - - return option -end + #option parsing + option = {} + optparse = OptionParser.new do |opts| + opts.banner = "Build and packaging service command-line tool." + "\n" \ + + "\n" + "Usage: pkg-build -u [-o ] [-c] [-h] [-v]" + "\n" \ + + "\n" + "Options:" + "\n" + + opts.on('-u','--url ', 'remote package server url: http://127.0.0.1/dibs/unstable') do |url| + option[:url] = url + end + + option[:os] = nil + opts.on('-o','--os ', 'operating system ') do |os| + option[:os] = os + end + + option[:clean] = false + opts.on('-c','--clean', 'clean build') do + option[:clean] = true + end + + option[:rev] = false + #opts.on('-r','--rev', 'reverse build dependency check') do + # option[:rev] = true + #end + + opts.on('-h','--help', 'display help') do + puts opts + exit + end + + opts.on('-v','--version', 'display version') do + puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version() + exit + end + end + + optparse.parse! + + if option[:url].nil? or option[:url].empty? then + raise ArgumentError, "Usage: pkg-build -u [-o ] [-c] [-h]" + end + + return option +end diff --git a/src/common/Action.rb b/src/common/Action.rb new file mode 100644 index 0000000..ed18fb0 --- /dev/null +++ b/src/common/Action.rb @@ -0,0 +1,47 @@ +=begin + + Action.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +class Action + attr_accessor :time, :period + + def initialize( time, period ) + @time = time + @period = period + end + + + # initialize action + def init() + end + + + # execute action + def execute() + end + +end diff --git a/src/common/BuildComm.rb b/src/common/BuildComm.rb new file mode 100644 index 0000000..f80a9e2 --- /dev/null +++ b/src/common/BuildComm.rb @@ -0,0 +1,657 @@ +require "socket" + +=begin + + BuildComm.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +$LOAD_PATH.unshift File.dirname(__FILE__) +require "log" +require 'timeout' +require "net/ftp" +require 'thread' +require "FileTransferViaFTP" +require "FileTransferViaDirect" + +ATTEMPTS = ["first", "second", "third"] + +class BuildCommServer + VERSION = "1.7.0" + + private_class_method :new + + def initialize(port, log, ftp_url, cache_dir) + @port = port + @log = log + @ftp_url = ftp_url + @cache_dir = cache_dir + @tcp_server = TCPServer.open( port ) + @download_cache_mutex = Mutex.new + end + + def self.create(port, log, ftp_url=nil, cache_dir=nil) + # checking port is available + if port_open? port then + raise "Port \"#{port}\" is already in use." + end + + if log.nil? then + log = DummyLog.new + end + + # create cache dir if not nil + if not cache_dir.nil? and not File.exist? cache_dir then + FileUtils.mkdir_p cache_dir + end + + return new(port, log, ftp_url, cache_dir) + end + + + # wait for connection and handle request + def wait_for_connection(quit_loop) + while( not quit_loop ) + req = @tcp_server.accept + + begin + yield req if block_given? + rescue + @log.error $! + @log.error "Caught a connection exception" + req.close + end + end + end + + + # terminate + def terminate + @tcp_server.close() + end + + + # send_begin + def self.send_begin( req ) + send( req, "=BEGIN,#{VERSION}") + end + + + def self.send_end( req ) + send( req, "=END") + end + + + def self.send_chk( req ) + send( req, "=CHK" ) + end + + + def self.send( req, line ) + begin + if not req.nil? then + req.puts line + end + rescue + raise "Connection is closed" + end + end + + + def send_file(req, src_file) + begin + if not File.exist? src_file then + @log.error "\"#{src_file}\" file does not exist" + req.puts "ERROR" + return false + end + + req.puts "READY" + @log.info "Ready to send file" + + while line = req.gets() + tok = line.split(",").map { |x| x.strip } + cmd = tok[0].strip + case cmd + when "CHECK_TRANSPORTER" + type = tok[1].strip + case type + when "DIRECT" + transporter = FileTransferDirect.new(@log) + when "FTP" + if not @ftp_url.nil? then + url_contents = Utils.parse_ftpserver_url(@ftp_url) + ip = url_contents[0] + port = url_contents[1] + username = url_contents[2] + passwd = url_contents[3] + transporter = FileTransferFTP.new(@log, ip, port, username, passwd) + else + transporter = FileTransferFTP.new(@log) + end + else + req.puts "ERROR" + @log.error "Unsupported transporter type! : #{type}" + return false + end + + req.puts "TRANSPORTER_OK" + + if not transporter.send_file( src_file, req, false ) then + return false + else + return true + end + + else + @log.warn "Unhandled message: #{line}" + end + end + + rescue => e + puts "[BuildCommServer] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return false + end + + return true + end + + + # NOTE. dst_file can be directory + def receive_file(req, dst_file) + begin + req.puts "READY" + @log.info "Ready to receive file" + + while line = req.gets() + tok = line.split(",").map { |x| x.strip } + cmd = tok[0].strip + case cmd + when "CHECK_CACHE" + file_name = tok[1] + file_size = tok[2].to_i + checksum = tok[3] + + # check download cache + if File.exist? dst_file and File.directory? dst_file then + target_file = File.join(dst_file,file_name) + else + target_file = dst_file + end + if not @cache_dir.nil? and + check_download_cache( target_file, file_size, checksum ) then + + @log.info "Download cache hit! Copied from cache.: #{file_name}" + req.puts "CACHED" + else + @log.info "Cached file not found!#{file_name}" + req.puts "NOT_CACHED" + end + + when "CHECK_TRANSPORTER" + type = tok[1].strip + case type + when "DIRECT" + transporter = FileTransferDirect.new(@log) + when "FTP" + if not @ftp_url.nil? then + url_contents = Utils.parse_ftpserver_url(@ftp_url) + ip = url_contents[0] + port = url_contents[1] + username = url_contents[2] + passwd = url_contents[3] + transporter = FileTransferFTP.new(@log, ip, port, username, passwd) + else + transporter = FileTransferFTP.new(@log) + end + else + req.puts "ERROR" + @log.error "Unsupported transporter type! : #{type}" + return false + end + + req.puts "TRANSPORTER_OK" + + if not transporter.receive_file( dst_file, req, false ) then + return false + end + + # add to cache + if not @cache_dir.nil? then + add_download_cache(target_file) + end + break + + else + @log.warn "Unhandled message: #{line}" + end + end + rescue => e + puts "[BuildCommServer] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return false + end + + return true + end + + + def self.disconnect( req ) + begin + req.close + rescue + end + end + + def self.port_open?( port ) + Timeout::timeout(1) do + begin + TCPSocket.new("127.0.0.1",port).close + true + rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH + false + end + end + rescue Timeout::Error + false + end + + + private + def check_download_cache(dst_file, file_size, checksum ) + file_name = File.basename(dst_file) + cache_file = "#{@cache_dir}/#{file_name}" + + @download_cache_mutex.synchronize do + found = false + # check file exist + if File.exist? cache_file and + File.size(cache_file) == file_size and + Utils.checksum(cache_file) == checksum then + + # if hit , touch and copy + FileUtils.touch cache_file + FileUtils.copy_file(cache_file, dst_file) + + found = true + end + + # refresh cache dir + curr_time = Time.now + Dir.entries(@cache_dir).each do |fname| + if fname == "." or fname == ".." then next end + file_path = "#{@cache_dir}/#{fname}" + if File.mtime(file_path) + 3600 < curr_time then + FileUtils.rm_rf file_path + end + end + + return found + end + end + + + private + def add_download_cache(dst_file) + file_name = File.basename(dst_file) + cache_file = "#{@cache_dir}/#{file_name}" + @download_cache_mutex.synchronize do + # copy & touch + FileUtils.copy_file(dst_file, cache_file) + FileUtils.touch cache_file + end + end +end + + +class BuildCommClient + VERSION = "1.7.0" + FIRST_REPONSE_TIMEOUT = 120 + + private_class_method :new + + def initialize(socket, log) + @log = log + @socket = socket + @error_msg = "" + end + + + # create + # if sec 0 or nil then not set timeout. it's timeout spec + def self.create(ip, port, log = nil, sec = 5) + # open socket + socket = nil + begin + timeout(sec) do + socket = TCPSocket.open( ip, port ) + end + rescue Timeout::Error + return nil + rescue + # unknown exception + return nil + end + + # refused + if socket.nil? then + return nil + end + + if log.nil? then + log = DummyLog.new + end + + return new(socket, log) + end + + + def get_error_msg() + return @error_msg + end + + + def set_error_msg( msg ) + @error_msg = msg + end + + + def send( msg ) + if @socket.nil? then + @error_msg = "Connection is not available!" + return false + end + + @socket.puts( msg ) + return true + end + + + def print_stream + + begin + l = nil + timeout(FIRST_REPONSE_TIMEOUT) do + l = @socket.gets() + end + + if l.nil? then + @error_msg = "Connection closed or no more message" + return false + end + + # check protocol + if not protocol_matched? l.strip then + @error_msg = "Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!" + return false + end + + # get contents + while line = @socket.gets() + if line.strip == "=END" then break end + if line.strip == "=CHK" then next end + # print + puts line.strip + end + rescue Timeout::Error + @error_msg = "Connection timed out!" + return false + + rescue => e + @error_msg = e.message + return false + end + + return true + end + + + # handle + def read_lines + + begin + # get first line + l = nil + timeout(FIRST_REPONSE_TIMEOUT) do + l = @socket.gets() + end + + if l.nil? then + @error_msg = "Connection closed or No more message" + return false + end + + # check protocol + if not protocol_matched? l.strip then + @error_msg = "Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!" + return false + end + + # get contents + result = true + while line = @socket.gets() + if line.strip == "=END" then break end + if line.strip == "=CHK" then next end + + # execute + yield line.strip if block_given? + end + rescue Timeout::Error + @error_msg = "Connection timed out!" + return false + + rescue => e + @error_msg = e.message + return false + end + + return true + end + + + # return result + def receive_data + result = [] + + begin + l = nil + timeout(FIRST_REPONSE_TIMEOUT) do + l = @socket.gets() + end + + if l.nil? then + @error_msg = "Connection closed or No more message" + return nil + end + + # check protocol + if not protocol_matched? l.strip then + @error_msg = "Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!" + return nil + end + + # get contents + while line = @socket.gets() + if line.strip == "=END" then break end + if line.strip == "=CHK" then next end + # print + result.push line.strip + end + + rescue Timeout::Error + @error_msg = "Connection timed out!" + return nil + + rescue => e + @error_msg = e.message + return nil + end + + return result + end + + + def send_file(src_file, transporter ) + + result = true + begin + l = @socket.gets() + if l.nil? then + @log.error "[BuildCommClient] Connection refused" + return false + end + + # check protocol + if not protocol_matched? l.strip then + @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!" + return false + end + + while line = @socket.gets() + cmd = line.split(",")[0].strip + case cmd + when "READY" + @log.info "Server is ready!" + file_name = File.basename(src_file) + file_size = File.size(src_file) + checksum = Utils.checksum(src_file) + send "CHECK_CACHE,#{file_name},#{file_size},#{checksum}" + + when "CACHED" + @log.info "Server already has cached file" + break + + when "NOT_CACHED" + @log.info "Server does not have cached file" + send "CHECK_TRANSPORTER,#{transporter.type}" + + when "TRANSPORTER_OK" + if not transporter.send_file( src_file, @socket, true ) then + result = false + else + @log.info "Sending file succeeded!" + end + + when "TRANSPORTER_FAIL" + @log.warn "Server does not support transporter type: #{transporter.type}" + result = false + + when "ERROR" + result = false + + when "=END" + break + + else + @log.warn "Unhandled message: #{line}" + end + end + rescue => e + puts "[BuildCommClient] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return false + end + + return result + end + + + # return file + def receive_file(dst_file, transporter) + result = true + + begin + l = @socket.gets() + + if l.nil? then + @log.error "[BuildCommClient] Connection refused" + return false + end + + # check protocol + if not protocol_matched? l.strip then + @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!" + return false + end + + while line = @socket.gets() + cmd = line.split(",")[0].strip + case cmd + when "READY" + @log.info "Server is ready!" + send "CHECK_TRANSPORTER,#{transporter.type}" + + when "TRANSPORTER_OK" + if not transporter.receive_file( dst_file, @socket, true ) then + result = false + else + @log.info "Receiving file succeeded!" + end + + when "ERROR" + result = false + + when "=END" + break + + else + @log.warn "Unhandled message: #{line}" + end + end + rescue => e + puts "[BuildCommServer] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return false + end + + return result + end + + + def terminate + @socket.close + end + + + private + + + # check protocol + def protocol_matched?(l) + + version = ( l.split(",")[1].nil? ? "1.0.0" : l.split(",")[1] ) + if not l.start_with? "=BEGIN" or + version.nil? or version != VERSION then + return false + else + return true + end + end +end diff --git a/src/common/FileTransferViaDirect.rb b/src/common/FileTransferViaDirect.rb new file mode 100644 index 0000000..d45f79e --- /dev/null +++ b/src/common/FileTransferViaDirect.rb @@ -0,0 +1,138 @@ +=begin + + FileTransferViaDirect.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'socket' +require 'log' + +class FileTransferDirect + attr_accessor :type + + def initialize(logger) + @type = "DIRECT" + + if not logger.nil? then + @log = logger + else + @log = DummyLog.new + end + end + + + def send_file( src_file, conn, is_client=true ) + + filename = File.basename(src_file) + size = File.size( src_file ) + checksum = Utils.checksum( src_file ) + + if is_client then + conn.puts "RECEIVE_REQ" + end + + while line = conn.gets() + tok = line.split(",") { |x| x.strip } + cmd = tok[0].strip + case cmd + when "SEND_REQ" + conn.puts "FILE_INFO,#{filename},#{size},#{checksum}" + # read file contents + # send via tcp/ip + File.open(src_file, "rb") do |io| + while size > 0 + buf = io.read(size > 1024*1024 ? 1024*1024 : size) + conn.write( buf ) + size -= buf.length + end + end + + @log.info "Upload is succeeded!" + conn.puts "SEND_OK" + + # wait for download result + when "RECEIVE_OK" + @log.info "Received download success message from remote site" + return true + + when "RECEIVE_FAIL" + @log.info "Received download fail message from remote site" + return false + + else + @log.error "Unhandled message: #{line}" + return false + end + end + end + + + def receive_file( dst_file, conn, is_client=false ) + + if is_client then + conn.puts "SEND_REQ" + end + + while line = conn.gets() + tok = line.split(",") { |x| x.strip } + cmd = tok[0].strip + case cmd + when "RECEIVE_REQ" + conn.puts "SEND_REQ" + when "FILE_INFO" + @log.info "Received file info from remote site" + filename = tok[1].strip + size = tok[2].strip.to_i + checksum = tok[3].strip + + if File.directory? dst_file then + dst_file = File.join(dst_file, filename) + end + + File.open( dst_file, "wb" ) do |io| + while size > 0 + buf = conn.read(size > 1024*1024 ? 1024*1024 : size) + if buf.nil? then + @log.error "Reading data from connection failed!" + return false + end + io.write( buf ) + size -= buf.length + end + end + + conn.puts "RECEIVE_OK" + + when "SEND_OK" + @log.info "Received success message from remote site" + return true + + else + @log.error "Unhandled message: #{line}" + return false + end + end + end +end diff --git a/src/common/FileTransferViaFTP.rb b/src/common/FileTransferViaFTP.rb new file mode 100644 index 0000000..71a14d0 --- /dev/null +++ b/src/common/FileTransferViaFTP.rb @@ -0,0 +1,288 @@ +=begin + + FileTransferViaFTP.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'socket' +require 'log' + +class FileTransferFTP + attr_accessor :type + ATTEMPTS = ["first", "second", "third"] + + def initialize(logger, ip=nil, port=nil, username=nil, passwd=nil ) + @type = "FTP" + @ip = ip + @port = port + @username = username + @passwd = passwd + if not logger.nil? then + @log = logger + else + @log = DummyLog.new + end + end + + + def send_file( src_file, conn, is_client=true ) + + if is_client then + # check ftp info + if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then + @log.error "No FTP information!" + conn.puts "UPLOAD_FAIL" + return false + end + conn.puts "DOWNLOAD_REQ,#{@ip},#{@port},#{@username},#{@passwd}" + end + + ip = @ip; port = @port; username = @username; passwd = @passwd + while line = conn.gets() + tok = line.split(",") { |x| x.strip } + cmd = tok[0].strip + case cmd + when "UPLOAD_REQ" + if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then + ip = tok[1].strip + port = tok[2].strip + username = tok[3].strip + passwd = tok[4].strip + @log.info "Using FTP information from remote... [#{ip}, #{port}]" + end + + # upload to ftp + ftp_filepath = nil + for attempt in ATTEMPTS + ftp_filepath = putfile( src_file, ip, port, username, passwd ) + if !ftp_filepath.nil? then + break + else + @log.info "The #{attempt} uploading attempt failed!" + end + end + + if ftp_filepath.nil? then + conn.puts "UPLOAD_FAIL" + return false + else + @log.info "Upload is succeeded at #{attempt}" + conn.puts "UPLOAD_OK,#{ftp_filepath}" + end + + # wait for download result + when "DOWNLOAD_OK" + @log.info "Received download success message from remote site" + # clean + cleandir( ftp_filepath, ip, port, username, passwd) + @log.info "Cleaned temporary dir on FTP server: #{ftp_filepath}" + return true + + when "DOWNLOAD_FAIL" + @log.info "Received download fail message from remote site" + return false + + else + @log.error "Unhandled message: #{line}" + return false + end + end + end + + + def receive_file( dst_file, conn, is_client=false ) + + if is_client then + # check ftp info + if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then + @log.error "No FTP information!" + conn.puts "DOWNLOAD_FAIL" + return false + end + conn.puts "UPLOAD_REQ,#{@ip},#{@port},#{@username},#{@passwd}" + end + + ip = @ip; port = @port; username = @username; passwd = @passwd + while line = conn.gets() + tok = line.split(",") { |x| x.strip } + cmd = tok[0].strip + case cmd + when "DOWNLOAD_REQ" + if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then + ip = tok[1].strip + port = tok[2].strip + username = tok[3].strip + passwd = tok[4].strip + @log.info "Using FTP information from remote... [#{ip}, #{port}]" + end + + conn.puts "UPLOAD_REQ,#{ip},#{port},#{username},#{passwd}" + when "UPLOAD_OK" + @log.info "Received upload success message from remote site" + filepath = tok[1].strip + # download from ftp + dst_filepath = nil + for attempt in ATTEMPTS + dst_filepath = getfile( filepath, dst_file, ip, port, username, passwd ) + if not dst_filepath.nil? then + break + else + @log.info "The #{attempt} downloading attempt failed!" + end + end + if dst_filepath.nil? then + conn.puts "DOWNLOAD_FAIL" + return false + else + @log.info " Server is the #{attempt} successful attempt to download" + conn.puts "DOWNLOAD_OK" + return true + end + + when "UPLOAD_FAIL" + @log.info "Received upload fail message from remote site" + return false + + else + @log.error "Unhandled message: #{line}" + return false + end + end + end + + + def putfile( bpath, ip, port, username, passwd ) + filename = File.basename(bpath) + uniqdir = Utils.create_uniq_name + ftp_filepath = File.join(uniqdir, filename) + + begin + ftp = Net::FTP.new + if port.nil? or port == "" then + ftp.connect(ip) + else + ftp.connect(ip, port) + end + @log.info "[FTP log] Connected FTP server (#{ip}:#{port})" + ftp.login(username, passwd) + ftp.binary = true + ftp.passive = true + ftp.mkdir(uniqdir) + ftp.chdir(uniqdir) + ftp.put(bpath) + @log.info "[FTP log] Put a file" + @log.info "[FTP log] from \"#{bpath}\" to \"#{ftp_filepath}\"" + files = ftp.list(filename) + if files.empty? then + @log.error "[FTP log] Failed to upload file (#{filename} does not exist)" + return nil + end + ftp.quit + @log.info "[FTP log] Disconnected FTP server" + rescue => e + @log.error "[FTP log] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return nil + end + return ftp_filepath + end + + def getfile( bpath, target, ip, port, username, passwd ) + dirname = File.dirname(bpath) + filename = File.basename(bpath) + + # target can be directory or file + if File.directory? target then + dst_file = File.join(target,filename) + else + dst_file = target + end + + begin + ftp = Net::FTP.new + if port.nil? or port == "" then + ftp.connect(ip) + else + ftp.connect(ip, port) + end + @log.info "[FTP log] Connected FTP server (#{ip}:#{port})" + ftp.login(username, passwd) + ftp.binary = true + ftp.passive = true + ftp.chdir(dirname) + ftp.get(filename, dst_file) + @log.info "[FTP log] Get a file" + @log.info "[FTP log] from \"#{bpath}\" to \"#{dst_file}\"" + ftp.quit + @log.info "[FTP log] Disconnected FTP server" + rescue => e + @log.error "[FTP log] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return nil + end + if not File.exist? dst_file then + @log.error "[FTP log] Failed to download file (#{dst_file} does not exist)" + return nil + end + return bpath + end + + def cleandir(path, ip, port, username, passwd) + dirname = File.dirname(path) + + begin + ftp = Net::FTP.new + if port.nil? or port == "" then + ftp.connect(ip) + else + ftp.connect(ip, port) + end + @log.info "[FTP log] Connected FTP server (#{ip}:#{port})" + ftp.login(username, passwd) + old_dir = ftp.pwd + ftp.chdir(dirname) + list = ftp.ls + # TODO: if list is directory? + list.each do |l| + file = l.split(" ")[-1].strip + ftp.delete(file) + end + ftp.chdir(old_dir) + ftp.rmdir(dirname) + @log.info "[FTP log] Clean dir (#{dirname})" + ftp.quit + @log.info "[FTP log] Disconnected FTP server" + rescue => e + @log.error "[FTP log] Exception" + @log.error e.message + @log.error e.backtrace.inspect + return nil + end + + return true + end +end diff --git a/src/common/PackageManifest.rb b/src/common/PackageManifest.rb index 4a9c2d3..c946dd2 100644 --- a/src/common/PackageManifest.rb +++ b/src/common/PackageManifest.rb @@ -1,5 +1,5 @@ =begin - + PackageManifest.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -33,45 +33,38 @@ class PackageManifest attr_accessor :packages def initialize( file_path ) - @pkg_map = Parser.read_pkginfo_list( file_path ) - @packages = @pkg_map.values + @packages = Parser.read_multy_pkginfo_from file_path end # scan all build dependencies - def get_build_dependencies( target_os, host_os ) + def get_build_dependencies( target_os ) # for all list = [] - for pkg in @packages + @packages.each do |pkg| # package that has the target os - if not pkg.os.include?(target_os) + if not pkg.os_list.include?(target_os) next end - # package that has the host os - if not pkg.build_host_os.include?(host_os) - next - end # package that has the target os - for dep in pkg.build_dep_list - # if dep.target_os_list.include? target_os - list.push dep - # end + pkg.build_dep_list.each do |dep| + list.push dep end end list.uniq! - + return list - end + end - - # scan all build dependencies + + # scan all source dependencies def get_source_dependencies( target_os, host_os ) # for all list = [] - for pkg in @packages + @packages.each do |pkg| # only package that used in target os - if not pkg.os.include?(target_os) + if not pkg.os_list.include?(target_os) next end @@ -81,27 +74,79 @@ class PackageManifest end # package that has the target os - for dep in pkg.source_dep_list - # if dep.target_os_list.include? target_os - list.push dep - # end + pkg.source_dep_list.each do |dep| + # if dep.target_os_list.include? target_os + list.push dep + # end + end + end + list.uniq! + + return list + end + + + # scan all install dependencies + def get_install_dependencies( target_os, pkg_name=nil ) + # for all + list = [] + @packages.each do |pkg| + if not pkg_name.nil? and pkg.package_name != pkg_name then next end + # only package that used in target os + if not pkg.os_list.include?(target_os) + next + end + + # package that has the target os + pkg.install_dep_list.each do |dep| + list.push dep end end list.uniq! return list - end + end def package_exist?(target_os, host_os) - for pkg in @packages + @packages.each do |pkg| # only package that used in target os - if pkg.os.include?(target_os) and + if pkg.os_list.include?(target_os) and pkg.build_host_os.include?(host_os) return true end end return false - end + end + + + def get_version() + return @packages[0].version + end + + + def get_target_packages(target_os) + pkgs = [] + @packages.each do |pkg| + if pkg.os_list.include?(target_os) then + pkgs.push pkg + end + end + + return pkgs + end + + + def pkg_exist?(name,ver,os) + @packages.each do |pkg| + if pkg.package_name != name then next end + if not ver.nil? and pkg.version != ver then next end + if not os.nil? and not pkg.os_list.include?(os) then next end + + return true + end + + return false + end end diff --git a/src/common/ScheduledActionHandler.rb b/src/common/ScheduledActionHandler.rb new file mode 100644 index 0000000..edbd691 --- /dev/null +++ b/src/common/ScheduledActionHandler.rb @@ -0,0 +1,117 @@ +=begin + + ScheduledActionHandler.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +$LOAD_PATH.unshift File.dirname(__FILE__) +require 'thread' + +class ScheduledActionHandler + attr_accessor :quit, :thread + + # init + def initialize( ) + @thread = nil + @quit = false + @actions = [] + @mutex = Mutex.new + end + + + # register a action + def register( action ) + # init action + action.init + # add to list + @mutex.synchronize do + @actions.push action + end + end + + + # unregsister a action + def unregister( action ) + @mutex.synchronize do + @actions.delete(action) + end + end + + + # get all actions + def get_actions() + return @actions + end + + + # start thread + def start() + @thread = Thread.new do + # main + thread_main() + + # close + terminate() + end + end + + + protected + + def thread_main + + while not @quit + + current_time = Time.new + + # get list + action_list = Array.new(@actions) + action_list.each do |action| + # if its time is reached, execute action + if not action.time.nil? and current_time > action.time then + action.execute + + # if periodic action, renew the time + # else remove it from list + if action.period != 0 then + while current_time > action.time + action.time = action.time + action.period + end + else + unregister(action) + end + end + end + + # sleep 10 sec + sleep 10 + end + end + + + def terminate + end + +end diff --git a/src/common/Version.rb b/src/common/Version.rb index 3bdba12..7d7921d 100644 --- a/src/common/Version.rb +++ b/src/common/Version.rb @@ -1,5 +1,5 @@ =begin - + Version.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -28,22 +28,11 @@ Contributors: class Version < Array - def initialize s - super(s.split('.').map { |e| e.to_i }) - end - def < x - (self <=> x) < 0 - end - def <= x - (self <=> x) <= 0 - end - def > x - (self <=> x) > 0 - end - def >= x - (self <=> x) >= 0 - end - def == x - (self <=> x) == 0 - end -end + include Comparable + def initialize s + super(s.split('.').map { |e| e.to_i }) + end + def compare x + self <=> x + end +end diff --git a/src/common/dependency.rb b/src/common/dependency.rb index a6e9499..74b5ae6 100644 --- a/src/common/dependency.rb +++ b/src/common/dependency.rb @@ -1,5 +1,5 @@ =begin - + dependency.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -27,31 +27,31 @@ Contributors: =end $LOAD_PATH.unshift File.dirname(__FILE__) -require "Version" +require "Version" class Dependency - attr_accessor :package_name, :comp, :base_version, :target_os_list - def initialize (package_name, comp, base_version, target_os_list) - @package_name = package_name - @comp = comp - @base_version = base_version - @target_os_list = target_os_list - end + attr_accessor :package_name, :comp, :base_version, :target_os_list + def initialize (package_name, comp, base_version, target_os_list) + @package_name = package_name + @comp = comp + @base_version = base_version + @target_os_list = target_os_list + end - def to_s - string = @package_name - if not @comp.nil? and not @base_version.nil? then - string = string + " ( #{@comp} #{@base_version} )" - end - - if not @target_os_list.empty? then - string = string + " [ #{@target_os_list.join("|")} ]" - end - return string - end + def to_s + string = @package_name + if not @comp.nil? and not @base_version.nil? then + string = string + " ( #{@comp} #{@base_version} )" + end + + if not @target_os_list.empty? then + string = string + " [ #{@target_os_list.join("|")} ]" + end + return string + end def match? ver - if @base_version.nil? + if @base_version.nil? return true end @@ -68,7 +68,7 @@ class Dependency return Version.new(ver) < Version.new(@base_version) else return true - end + end end -end +end diff --git a/src/common/execute_with_log.rb b/src/common/execute_with_log.rb new file mode 100755 index 0000000..58cb982 --- /dev/null +++ b/src/common/execute_with_log.rb @@ -0,0 +1,56 @@ +#!/usr/bin/ruby +=begin + + execute_with_log.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'logger' +$LOAD_PATH.unshift File.dirname(__FILE__) +require 'utils.rb' + +# parse arguments +cmd = ARGV[0] +log_path = ARGV[1] + +# create logger +if log_path.nil? or log_path.empty? then + log = DummyLog.new +else + log = Logger.new(log_path) +end + +# generate command +cmd = Utils.generate_shell_command(cmd, nil) + +# execute and write log +IO.popen("#{cmd} 2>&1") do |io| + io.each do |line| + log.info line + end +end + +# return exit code +exit $?.exitstatus diff --git a/src/common/log.rb b/src/common/log.rb index afa8fd7..893885f 100644 --- a/src/common/log.rb +++ b/src/common/log.rb @@ -1,5 +1,5 @@ =begin - + log.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -30,7 +30,7 @@ require "logger" class Log - attr_accessor :path + attr_accessor :path, :cnt # Log LEVEL LV_NORMAL = 1 @@ -39,7 +39,8 @@ class Log # init def initialize(path, lv=LV_USER) - @path = path + @cnt = 0 + @path = path if @path.nil? then @logger = Logger.new(STDOUT) else @@ -52,43 +53,47 @@ class Log # diable logger format @default_formatter = @logger.formatter @no_prefix_formatter = proc do |severity, datetime, progname, msg| - " >#{msg}" + " >#{msg}" end end def info(msg, lv=LV_NORMAL) - if @path.nil? then puts "Info: #{msg}" - else @logger.info msg end - if not @second_out.nil? and lv >= @second_out_level then - output_extra "Info: " + msg + if @path.nil? and not @second_out.nil? then puts "Info: #{msg}" + else @logger.info msg end + if not @second_out.nil? and lv >= @second_out_level then + output_extra "Info: " + msg end - end + @cnt = @cnt + 1 + end - def warn(msg, lv=LV_NORMAL) - if @path.nil? then puts "Warn: #{msg}" + def warn(msg, lv=LV_NORMAL) + if @path.nil? and not @second_out.nil? then puts "Warn: #{msg}" else @logger.warn msg end if not @second_out.nil? and lv >= @second_out_level then - output_extra "Warn: " + msg + output_extra "Warn: " + msg end - end + @cnt = @cnt + 1 + end - def error(msg, lv=LV_NORMAL) - if @path.nil? then puts "Error: #{msg}" + def error(msg, lv=LV_NORMAL) + if @path.nil? and not @second_out.nil? then puts "Error: #{msg}" else @logger.error msg end if not @second_out.nil? and lv >= @second_out_level then - output_extra "Error: " + msg + output_extra "Error: " + msg end + @cnt = @cnt + 1 end - def output(msg, lv=LV_NORMAL) - if @path.nil? then puts msg + def output(msg, lv=LV_NORMAL) + if @path.nil? and not @second_out.nil? then puts msg else @logger.info msg end if not @second_out.nil? and lv >= @second_out_level then - output_extra msg + output_extra msg end + @cnt = @cnt + 1 end @@ -96,10 +101,47 @@ class Log @second_out= nil end + def is_verbose + return @second_out_level.eql? Log::LV_NORMAL + end + protected def output_extra(msg) - #do nothing - end + #do nothing + end +end + +class DummyLog + attr_accessor :path, :cnt + def initialize() + @path = "" + @cnt = 0 + end + def info(str, lv=nil) + puts "I, [#{Time.now.strftime("%Y-%m-%dT%H:%M:%S")}] INFO -- : " + str + end + def error(str, lv=nil) + puts "E, [#{Time.now.strftime("%Y-%m-%dT%H:%M:%S")}] ERROR -- : " + str + end + def warn(str, lv=nil) + puts "W, [#{Time.now.strftime("%Y-%m-%dT%H:%M:%S")}] WARN -- : " + str + end + def output(str, lv=nil) + puts "" + str + end +end + +class StandardOutLog < Log + + def initialize(path) + super(path) + @second_out = $stdout + end + + protected + def output_extra(msg) + @second_out.puts msg + end end diff --git a/src/common/mail.rb b/src/common/mail.rb index a49c1d2..aedc753 100644 --- a/src/common/mail.rb +++ b/src/common/mail.rb @@ -1,5 +1,5 @@ =begin - + mail.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -30,15 +30,15 @@ require 'net/smtp' $LOAD_PATH.unshift File.dirname(__FILE__) require "mailConfig" -class Mail +class Mail - def Mail.send_mail( mail_to, subject, contents ) + def Mail.send_mail( mail_to, subject, contents ) if mail_to.nil? or mail_to.empty? \ - or subject.nil? or subject.empty? \ - or contents.nil? or contents.empty? then + or subject.nil? or subject.empty? \ + or contents.nil? or contents.empty? then return false - end + end message = < e + begin + Net::SMTP.start('localhost') do |smtp| + smtp.send_message( message, SENDER, mail_to_list) + end + rescue => e puts "Can't send result email" puts e.message end @@ -69,18 +69,18 @@ MESSAGE_END def Mail.parse_email( low_email_list ) mail_list = [] - low_email_list.each do | low_email | + low_email_list.split(",").each do | low_email | ms = low_email.index('<') - me = low_email.index('>') - if ms.nil? or me.nil? then - next - else - mail = low_email[(ms+1)..(me-1)] - end - - if mail.include?("@") then mail_list.push mail end - end + me = low_email.index('>') + if ms.nil? or me.nil? then + next + else + mail = low_email[(ms+1)..(me-1)] + end + + if mail.include?("@") then mail_list.push mail end + end - return mail_list + return mail_list end end diff --git a/src/common/package.rb b/src/common/package.rb index 122f977..a7c139f 100644 --- a/src/common/package.rb +++ b/src/common/package.rb @@ -1,6 +1,6 @@ =begin - - package.rb + + package.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -27,135 +27,88 @@ Contributors: =end class Package - attr_accessor :package_name, :version, :os, :build_host_os, :maintainer, :attribute, :install_dep_list, :build_dep_list, :source_dep_list, :conflicts, :source, :src_path, :path, :origin, :checksum, :size, :description - def initialize (package_name) - @package_name = package_name - @version = "" - @os = "" - @build_host_os = [] - @maintainer = "" - @attribute = [] - @install_dep_list = [] - @build_dep_list = [] - @source_dep_list = [] - @conflicts = [] - @source = "" - @src_path = "" - @path = "" - @origin = "" - @checksum = "" - @size = "" - @description = "" - end - def print - puts "Package : " + @package_name - if not @version.empty? then puts "Version : " + @version end - if not @os.empty? then puts "OS : " + @os end - if not @build_host_os.empty? then puts "Build-host-os : " + @build_host_os.join("|") end - if not @maintainer.empty? then puts "Maintainer : " + @maintainer end - if not @attribute.empty? then puts "Attribute : " + @attribute.join("|") end - if not @install_dep_list.empty? then - puts "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ") - end - if not @build_dep_list.empty? then - puts "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ") - end - if not @source_dep_list.empty? then - puts "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ") - end - if not @conflicts.empty? then - puts "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ") - end - if not @source.empty? then puts "Source : " + @source end - if not @src_path.empty? then puts "Src-path : " + @src_path end - if not @path.empty? then puts "Path : " + @path end - if not @origin.empty? then puts "Origin : " + @origin end - if not @checksum.empty? then puts "SHA256 : " + @checksum end - if not @size.empty? then puts "Size : " + @size end - if not @description.empty? then puts "Description : " + @description end - end + attr_accessor :package_name, :label, :version, :os, :build_host_os, :maintainer, :attribute, :install_dep_list, :build_dep_list, :source_dep_list, :conflicts, :source, :src_path, :path, :origin, :checksum, :size, :description, :os_list, :custom, :change_log + def initialize (package_name) + @package_name = package_name + @label = "" + @version = "" + @os = "" + @os_list = [] + @build_host_os = [] + @maintainer = "" + @attribute = [] + @install_dep_list = [] + @build_dep_list = [] + @source_dep_list = [] + @conflicts = [] + @source = "" + @src_path = "" + @path = "" + @origin = "" + @checksum = "" + @size = "" + @description = "" + @custom = "" + @change_log = {} + end + + def print + puts self.to_s + end + + def to_s + string = "Package : " + @package_name + if not @label.empty? then string = string + "\n" + "Label : " + @label end + if not @version.empty? then string = string + "\n" + "Version : " + @version end + if not @os_list.empty? then string = string + "\n" + "OS : " + @os_list.join(", ") end + if not @build_host_os.empty? then string = string + "\n" + "Build-host-os : " + @build_host_os.join(", ") end + if not @maintainer.empty? then string = string + "\n" + "Maintainer : " + @maintainer end + if not @attribute.empty? then string = string + "\n" + "Attribute : " + @attribute.join("|") end + if not @install_dep_list.empty? then + string = string + "\n" + "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ") + end + if not @build_dep_list.empty? then + string = string + "\n" + "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ") + end + if not @source_dep_list.empty? then + string = string + "\n" + "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ") + end + if not @conflicts.empty? then + string = string + "\n" + "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ") + end + if not @source.empty? then string = string + "\n" + "Source : " + @source end + if not @src_path.empty? then string = string + "\n" + "Src-path : " + @src_path end + if not @path.empty? then string = string + "\n" + "Path : " + @path end + if not @origin.empty? then string = string + "\n" + "Origin : " + @origin end + if not @checksum.empty? then string = string + "\n" + "SHA256 : " + @checksum end + if not @size.empty? then string = string + "\n" + "Size : " + @size end + if not @custom.empty? then string = string + "\n" + @custom end + if not @description.empty? then string = string + "\n" + "Description : " + @description end + return string + end + + def print_to_file(file) + file.puts self.to_s + end + + def change_log_string + if @change_log.empty? then return "" end + + string = "" + @change_log.sort.each do |list| + string = "* " + list[0] + "\n" + list[1] + "\n" + string + end + return "#Change log\n" + string + end - def to_s - string = "Package : " + @package_name - if not @version.empty? then string = string + "\n" + "Version : " + @version end - if not @os.empty? then string = string + "\n" + "OS : " + @os end - if not @build_host_os.empty? then string = string + "\n" + "Build-host-os : " + @build_host_os.join("|") end - if not @maintainer.empty? then string = string + "\n" + "Maintainer : " + @maintainer end - if not @attribute.empty? then string = string + "\n" + "Attribute : " + @attribute.join("|") end - if not @install_dep_list.empty? then - string = string + "\n" + "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ") - end - if not @build_dep_list.empty? then - string = string + "\n" + "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ") - end - if not @source_dep_list.empty? then - string = string + "\n" + "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ") - end - if not @conflicts.empty? then - string = string + "\n" + "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ") - end - if not @source.empty? then string = string + "\n" + "Source : " + @source end - if not @src_path.empty? then string = string + "\n" + "Src-path : " + @src_path end - if not @path.empty? then string = string + "\n" + "Path : " + @path end - if not @origin.empty? then string = string + "\n" + "Origin : " + @origin end - if not @checksum.empty? then string = string + "\n" + "SHA256 : " + @checksum end - if not @size.empty? then string = string + "\n" + "Size : " + @size end - if not @description.empty? then string = string + "\n" + "Description : " + @description end - return string - end - def print_to_file(file) - file.puts "Package : " + @package_name - if not @version.empty? then file.puts "Version : " + @version end - if not @os.empty? then file.puts "OS : " + @os end - if not @build_host_os.empty? then file.puts "Build-host-os : " + @build_host_os.join("|") end - if not @maintainer.empty? then file.puts "Maintainer : " + @maintainer end - if not @attribute.empty? then file.puts "Attribute : " + @attribute.join("|") end - if not @install_dep_list.empty? then - file.puts "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ") - end - if not @build_dep_list.empty? then - file.puts "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ") - end - if not @source_dep_list.empty? then - file.puts "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ") - end - if not @conflicts.empty? then - file.puts "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ") - end - if not @source.empty? then file.puts "Source : " + @source end - if not @src_path.empty? then file.puts "Src-path : " + @src_path end - if not @path.empty? then file.puts "Path : " + @path end - if not @origin.empty? then file.puts "Origin : " + @origin end - if not @checksum.empty? then file.puts "SHA256 : " + @checksum end - if not @size.empty? then file.puts "Size : " + @size end - if not @description.empty? then file.puts "Description : " + @description end - end + def does_change_exist? + if not @change_log.empty? and not @change_log[@version].nil? then + return true + end + return false + end - def print_to_file_with_os(file,target_os) - file.puts "Package : " + @package_name - if not @version.empty? then file.puts "Version : " + @version end - file.puts "OS : " + target_os - if not @build_host_os.empty? then file.puts "Build-host-os : " + @build_host_os.join("|") end - if not @maintainer.empty? then file.puts "Maintainer : " + @maintainer end - if not @attribute.empty? then file.puts "Attribute : " + @attribute.join("|") end - if not @install_dep_list.empty? then - file.puts "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ") - end - if not @build_dep_list.empty? then - file.puts "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ") - end - if not @source_dep_list.empty? then - file.puts "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ") - end - if not @conflicts.empty? then - file.puts "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ") - end - if not @source.empty? then file.puts "Source : " + @source end - if not @src_path.empty? then file.puts "Src-path : " + @src_path end - if not @path.empty? then file.puts "Path : " + @path end - if not @origin.empty? then file.puts "Origin : " + @origin end - if not @checksum.empty? then file.puts "SHA256 : " + @checksum end - if not @size.empty? then file.puts "Size : " + @size end - if not @description.empty? then file.puts "Description : " + @description end - end -end + def get_changes + return @change_log[@version] + end +end diff --git a/src/common/parser.rb b/src/common/parser.rb index 01f7acf..87949e0 100644 --- a/src/common/parser.rb +++ b/src/common/parser.rb @@ -1,6 +1,6 @@ =begin - - parser.rb + + parser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -31,209 +31,290 @@ require "package" require "dependency" class Parser - def Parser.read_pkginfo_list (file) - pkglist = {} - File.open file,"r" do |f| - #variable initialize - package_name = "" - version = "" - os = "" - build_host_os = [] - maintainer = "" - attribute = [] - install_dep_list = [] - build_dep_list = [] - source_dep_list = [] - conflicts = [] - source = "" - src_path = "" - path = "" - origin = "" - checksum = "" - size = "" - description = "" - - f.each_line do |l| - # separator - if l.strip.empty? then - #make package and initialize - if not package_name.empty? and not os.empty? then - package = Package.new(package_name) - if not version.empty? then package.version = version end - if not os.empty? then package.os = os end - if not build_host_os.empty? then package.build_host_os = build_host_os end - if not maintainer.empty? then package.maintainer = maintainer end - if not attribute.empty? then package.attribute = attribute end - if not install_dep_list.empty? then package.install_dep_list = install_dep_list end - if not build_dep_list.empty? then package.build_dep_list = build_dep_list end - if not source_dep_list.empty? then package.source_dep_list = source_dep_list end - if not conflicts.empty? then package.conflicts = conflicts end - if not source.empty? then package.source = source end - if not src_path.empty? then package.src_path = src_path end - if not path.empty? then package.path = path end - if not origin.empty? then package.origin = origin end - if not checksum.empty? then package.checksum = checksum end - if not size.empty? then package.size = size end - if not description.empty? then package.description = description end - pkglist[[package_name,os]] = package - package_name = "" - version = "" - os = "" - bulid_host_os = [] - maintainer = "" - attribute = [] - install_dep_list = [] - build_dep_list = [] - source_dep_list = [] - conflicts = [] - source = "" - src_path = "" - path = "" - origin = "" - checksum = "" - size = "" - description = "" - end - next - end - # commant - if l.strip.start_with? "#" then next end - #contents - dsic_on = false - case l.strip.split(':')[0].strip - when /^Package/i then - package_name = l.sub(/^[ \t]*Package[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Version/i then - version = l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^OS/i then - os = l.sub(/^[ \t]*OS[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Build-host-os/i then - build_host_os = l.sub(/^[ \t]*Build-host-os[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split("|") - disc_on=false - when /^Maintainer/i then - maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Attribute/i then - attribute = l.sub(/^[ \t]*Attribute[ \t]*:[ \t]*/i,"").tr(" \t\n\r","").split("|") - disc_on=false - when /^Install-dependency/i then - install_dep_list = dep_parser l.sub(/^[ \t]*Install-dependency[ \t]*:[ \t]*/i,"").split(',') - disc_on=false - when /^Build-dependency/i then - build_dep_list = dep_parser l.sub(/^[ \t]*Build-dependency[ \t]*:[ \t]*/i,"").split(',') - disc_on=false - when /^Source-dependency/i then - source_dep_list = dep_parser l.sub(/^[ \t]*Source-dependency[ \t]*:[ \t]*/i,"").split(',') - disc_on=false - when /^Conflicts/i then - conflicts = dep_parser l.sub(/^[ \t]*Conflicts[ \t]*:[ \t]*/i,"").split(',') - disc_on=false - when /^Source/i then - source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Src-path/i then - src_path = l.sub(/^[ \t]*Src-path[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Path/i then - path = l.sub(/^[ \t]*Path[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Origin/i then - origin = l.sub(/^[ \t]*Origin[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^SHA256/i then - checksum = l.sub(/^[ \t]*SHA256[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Size/i then - size = l.sub(/^[ \t]*Size[ \t]*:[ \t]*/i,"").strip - disc_on=false - when /^Description/i then - description = l.sub(/^[ \t]*Description[ \t]*:[ \t]*/i,"") - disc_on=true - else - if disc_on then - description = description + l - else - puts "unknown section : #{l}" - end - end - - end - #i essent - - # check last package - if not package_name.empty? and not os.empty? then - package = Package.new(package_name) - if not version.empty? then package.version = version end - if not os.empty? then package.os = os end - if not build_host_os.empty? then package.build_host_os = build_host_os end - if not maintainer.empty? then package.maintainer = maintainer end - if not attribute.empty? then package.attribute = attribute end - if not install_dep_list.empty? then package.install_dep_list = install_dep_list end - if not build_dep_list.empty? then package.build_dep_list = build_dep_list end - if not source_dep_list.empty? then package.source_dep_list = source_dep_list end - if not conflicts.empty? then package.conflicts = conflicts end - if not source.empty? then package.source = source end - if not src_path.empty? then package.src_path = src_path end - if not path.empty? then package.path = path end - if not origin.empty? then package.origin = origin end - if not checksum.empty? then package.checksum = checksum end - if not size.empty? then package.size = size end - if not description.empty? then package.description = description end - pkglist[[package_name,os]] = package - end - end - return pkglist - end - - def Parser.read_pkginfo (file) - return read_pkg_list(file).values[0] - end - - def Parser.read_pkg_list (file) - result = {} - read_pkginfo_list(file).values.each { |x| result[x.package_name]=x } - return result - end - - private - def Parser.dep_parser (string_list) - dependency_list = [] - string_list.each do |dep| - #variable initialize - package_name = "" - comp = nil - base_version = nil - target_os_list = [] - #string trim - dependency = dep.tr " \t\n", "" - #version extract - vs = dependency.index('(') - ve = dependency.index(')') - if not vs.nil? and not ve.nil? then - comp = dependency[(vs+1)..(vs+2)] - base_version = dependency[(vs+3)..(ve-1)] - end - #os list extract - os = dependency.index('[') - oe = dependency.index(']') - if not os.nil? and not oe.nil? then - target_os_list = dependency[(os+1)..(oe-1)].split("|") - end - # package_name extract - pe = dependency.index(/[\]\[\)\(]/) - if pe.nil? - package_name = dependency - else - package_name = dependency[0..pe-1] - end - #package_name check - if not package_name.empty? then - dependency_list.push Dependency.new(package_name,comp,base_version,target_os_list) - end - end - return dependency_list - end -end + def Parser.read_multy_pkginfo_from (file, only_common = false) + pkglist = [] + package = nil + common_source = "" + common_version = "" + common_maintainer = "" + change_log = {} + multi_line = nil + change_version = nil + change_contents = "" + + #file check + + File.open file,"r" do |f| + #variable initialize + state = "INIT" + f.each_line do |l| + # commant + if l.strip.start_with? "#" then next end + + field_name = l.split(':')[0].strip + + case state + when "INIT" then + case field_name + when /^$/ then next + when /^Source$/i then + state = "COMMON" + if common_source.empty? then common_source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + when /^Version$/i then + state = "COMMON" + if common_version.empty? then common_version = check_version l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + when /^Maintainer$/i then + state = "COMMON" + if common_maintainer.empty? then common_maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + when /^Package$/i then + state = "PACKAGE" + package_name = l.sub(/^[ \t]*Package[ \t]*:[ \t]*/i,"").strip + if not package_name.empty? then + package = Package.new(package_name) + package.source = common_source + package.version = common_version + package.maintainer = common_maintainer + else + raise RuntimeError, "Package name is not set in \"#{file}\" file" + end + when /^\*[ \t]*([0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*)[ \t]*$/ then + state = "CHANGELOG" + change_log[change_version] = change_contents.strip if not change_version.nil? + change_version = $1 + change_contents = "" + when /^Include$/i then + pfile = File.dirname(file) + "/" + l.sub(/^[ \t]*Include[ \t]*:[ \t]*/i,"").strip + if File.exist? pfile then + pkglist = pkglist + (Parser.read_multy_pkginfo_from pfile) + list = Parser.read_multy_pkginfo_from(pfile, true) + common_source = list[0] if common_source.empty? + common_version = list[1] if common_version.empty? + common_maintainer = list[2] if common_maintainer.empty? + change_log = list[3] if change_log.empty? + else + raise RuntimeError, "Not exist \"#{pfile}\"" + end + when /^ORIGIN$/ then #for compatable + multi_line = nil + next + else raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}" + end + when "COMMON" then + case field_name + when /^$/ then state = "INIT" + when /^Source$/i then + state = "COMMON" + if common_source.empty? then common_source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + when /^Version$/i then + state = "COMMON" + if common_version.empty? then common_version = check_version l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + when /^Maintainer$/i then + state = "COMMON" + if common_maintainer.empty? then common_maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + when /^ORIGIN$/ then #for compatable + multi_line = nil + next + else raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}" + end + when "PACKAGE" then + case field_name + when /^$/ then + state = "INIT" + if not package.package_name.empty? then + pkglist.push package + package = nil + else raise RuntimeError, "Package name is not set in \"#{file}\" file" + end + multi_line = nil + when /^Source$/i then + if common_source.empty? and package.source.empty? then package.source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + multi_line = nil + when /^Version$/i then + if common_version.empty? and package.version.empty? then package.version = check_version l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + multi_line = nil + when /^Maintainer$/i then + if common_maintainer.empty? and package.maintainer.empty? then package.maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip + else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field" + end + multi_line = nil + when /^OS$/i then + package.os_list = l.sub(/^[ \t]*OS[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split(",") + package.os = package.os_list[0] + multi_line = nil + when /^Label$/i then + package.label = l.sub(/^[ \t]*Label[ \t]*:[ \t]*/i,"").strip + multi_line = nil + when /^Build-host-os$/i then + package.build_host_os = l.sub(/^[ \t]*Build-host-os[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split(",") + multi_line = nil + when /^Attribute$/i then + package.attribute = l.sub(/^[ \t]*Attribute[ \t]*:[ \t]*/i,"").tr(" \t\n\r","").split("|") + multi_line = nil + when /^Install-dependency$/i then + package.install_dep_list = dep_parser l.sub(/^[ \t]*Install-dependency[ \t]*:[ \t]*/i,"").split(',') + multi_line = nil + when /^Build-dependency$/i then + package.build_dep_list = dep_parser l.sub(/^[ \t]*Build-dependency[ \t]*:[ \t]*/i,"").split(',') + multi_line = nil + when /^Source-dependency$/i then + package.source_dep_list = dep_parser l.sub(/^[ \t]*Source-dependency[ \t]*:[ \t]*/i,"").split(',') + multi_line = nil + when /^Conflicts$/i then + package.conflicts = dep_parser l.sub(/^[ \t]*Conflicts[ \t]*:[ \t]*/i,"").split(',') + multi_line = nil + when /^Src-path$/i then + package.src_path = l.sub(/^[ \t]*Src-path[ \t]*:[ \t]*/i,"").strip + multi_line = nil + when /^Path$/i then + package.path = l.sub(/^[ \t]*Path[ \t]*:[ \t]*/i,"").strip + multi_line = nil + when /^Origin$/i then + package.origin = l.sub(/^[ \t]*Origin[ \t]*:[ \t]*/i,"").strip + multi_line = nil + when /^SHA256$/i then + package.checksum = l.sub(/^[ \t]*SHA256[ \t]*:[ \t]*/i,"").strip + multi_line = nil + when /^Size$/i then + package.size = l.sub(/^[ \t]*Size[ \t]*:[ \t]*/i,"").strip + multi_line = nil + when /^Description$/i then + package.description = l.sub(/^[ \t]*Description[ \t]*:[ \t]*/i,"").strip + multi_line = "Description" + when /^ORIGIN$/ then #for compatable + multi_line = nil + next + when /^C-/ then + if package.custom.empty? then package.custom = l.rstrip + else package.custom = package.custom + "\n" + l.rstrip + end + multi_line = nil + else + if multi_line.nil? then raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}" end + case multi_line + when "Description" then package.description = package.description + "\n" + l.rstrip + else raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}" + end + end + when "CHANGELOG" then + case field_name + when /^$/ then + state = "INIT" + if not change_version.nil? then + if change_log[change_version].nil? then change_log[change_version] = change_contents.strip + else raise RuntimeError, "change log version is duplicated in \"#{file}\" file \n\t#{l}" + end + end + change_version = nil + change_contents = "" + when /^\*[ \t]*([0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*)[ \t]*$/ then + if not change_version.nil? then + if change_log[change_version].nil? then change_log[change_version] = change_contents.strip + else raise RuntimeError, "change log version is duplicated in \"#{file}\" file \n\t#{l}" + end + end + change_version = $1 + change_contents = "" + else + change_contents = change_contents + "\n" + l.rstrip + end + else raise RuntimeError, "UNKNOWN state #{field_name}" + end + end + + # check last package + if not package.nil? then pkglist.push package end + if not change_version.nil? then + if change_log[change_version].nil? then change_log[change_version] = change_contents.strip + else raise RuntimeError, "change log version is duplicated in \"#{file}\" file \n\t#{change_version}" + end + end + pkglist.each {|pkg| pkg.change_log = change_log } + end + if only_common then return [common_source, common_version, common_maintainer, change_log] end + return pkglist + end + + def Parser.check_version(version) + if not version =~ /^[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*$/ then + raise RuntimeError, "Version format not matched \"#{version}\"\nVersion format must be \"{digit}.{digit}.{digit}\"" + end + return version + end + + def Parser.read_changelog(file) + return read_multy_pkginfo_from(file,true)[3] + end + + def Parser.read_single_pkginfo_from (file) + return read_multy_pkginfo_from(file)[0] + end + + def Parser.read_repo_pkg_list_from (file) + result = {} + read_multy_pkginfo_from(file).each { |x| result[x.package_name]=x } + return result + end + + #for test + def Parser.print (array) + array.each do |package| + puts package.to_s + puts "" + end + end + + private + def Parser.dep_parser (string_list) + dependency_list = [] + string_list.each do |dep| + #variable initialize + package_name = "" + comp = nil + base_version = nil + target_os_list = [] + #string trim + dependency = dep.tr " \t\r\n", "" + #version extract + vs = dependency.index('(') + ve = dependency.index(')') + if not vs.nil? and not ve.nil? then + comp = dependency[(vs+1)..(vs+2)] + base_version = dependency[(vs+3)..(ve-1)] + end + #os list extract + os = dependency.index('[') + oe = dependency.index(']') + if not os.nil? and not oe.nil? then + target_os_list = dependency[(os+1)..(oe-1)].split("|") + end + # package_name extract + pe = dependency.index(/[\]\[\)\(]/) + if pe.nil? + package_name = dependency + else + package_name = dependency[0..pe-1] + end + #package_name check + if not package_name.empty? then + dependency_list.push Dependency.new(package_name,comp,base_version,target_os_list) + end + end + return dependency_list + end +end diff --git a/src/common/utils.rb b/src/common/utils.rb index 24b12ff..abae33c 100644 --- a/src/common/utils.rb +++ b/src/common/utils.rb @@ -1,6 +1,6 @@ =begin - - utils.rb + + utils.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -25,178 +25,304 @@ limitations under the License. Contributors: - S-Core Co., Ltd =end +require 'rbconfig' class Utils + STARTUP_INFO_SIZE = 68 + PROCESS_INFO_SIZE = 16 + NORMAL_PRIORITY_CLASS = 0x00000020 + + def Utils.identify_current_OS() + os = "UnsupportedOS" - if defined?(HOST_OS).nil? then case `uname -s`.strip - when "Linux" - HOST_OS = "linux" - when /MINGW32.*/ - HOST_OS = "windows" - when "Darwin" - HOST_OS = "darwin" - else - end + when "Linux" + if File.exist? "/etc/debian_version" then + arch = (`uname -i`.strip == "x86_64") ? "64" : "32" + os = "ubuntu-#{arch}" + elsif File.exist? "/etc/redhat-release" then + os = "redhat-unknown" + elsif File.exist? "/etc/SuSE-release" then + arch = (`uname -i`.strip == "x86_64") ? "64" : "32" + os = "opensuse-#{arch}" + elsif File.exist? "/etc/mandrake-release" then + os = "mandrake-unknown" + end + when "MINGW32_NT-5.1" + progfile_path = Utils.execute_shell_return("echo $PROGRAMFILES","windows")[0].strip + if progfile_path.include?("(x86)") then arch = "64" else arch = "32" end + os = "windows-#{arch}" + when "MINGW32_NT-6.1" + progfile_path = Utils.execute_shell_return("echo $PROGRAMFILES","windows")[0].strip + if progfile_path.include?("(x86)") then arch = "64" else arch = "32" end + os = "windows-#{arch}" + when "Darwin" + os = "macos-64" + end + + return os end - # set static variable in WORKING_DIR, HOME - if defined?(WORKING_DIR).nil? then WORKING_DIR = Dir.pwd end - if defined?(HOME).nil? then - # get home directory, using Dir.chdir - Dir.chdir - HOME = Dir.pwd - Dir.chdir WORKING_DIR - end - - def Utils.create_uniq_name - time = Time.new - # uniq snapshot_name name is year_month_day_hour_min_sec_microsec - return time.strftime("%m%d%H%M%S") + time.usec.to_s() - end - - def Utils.is_url_remote(url) - if url.nil? then - return false - end - - protocol = url.split(':')[0] - - case protocol - when "http" then - return true - else - return false - end - end - - # if source_ver > target_ver, return -1 - # if source_ver < target_ver, return 1 - # if source_ver == target_ver, return 0 - def Utils.compare_version(source_ver, target_ver) - sver = source_ver.split('-')[0] - tver = target_ver.split('-')[0] - - arr_sver = sver.split('.') - arr_tver = tver.split('.') - - slen = arr_sver.length - tlen = arr_tver.length - len = tlen - - if slen > tlen then - gap = slen - tlen - gap.times do - arr_tver.push("0") - end - len = slen - elsif tlen > slen then - gap = tlen - slen - gap.times do - arr_sver.push("0") - end - len = tlen - end - - len.times do |i| - if arr_sver[i].to_i < arr_tver[i].to_i then - return 1 - elsif arr_sver[i].to_i > arr_tver[i].to_i then - return -1 - end - end - - return 0 - end - - - def Utils.execute_shell(cmd) - ret = false - if HOST_OS.eql? "windows" then + + def Utils.check_host_OS() + if Utils.get_all_OSs().include? HOST_OS then + return true + else + return false + end + end + + + def Utils.get_all_OSs() + return ["ubuntu-32","ubuntu-64","windows-32","windows-64","macos-64","opensuse-32", "opensuse-64"] + end + + + def Utils.create_uniq_name + time = Time.new + + # uniq snapshot_name name is year_month_day_hour_min_sec_microsec + return time.strftime("%m%d%H%M%S") + time.usec.to_s.rjust(6, '0') + end + + def Utils.is_url_remote(url) + if url.nil? then + return false + end + + protocol = url.split(':')[0] + + case protocol + when "http" then + return true + else + return false + end + end + + # if source_ver > target_ver, return -1 + # if source_ver < target_ver, return 1 + # if source_ver == target_ver, return 0 + def Utils.compare_version(source_ver, target_ver) + sver = source_ver.split('-')[0] + tver = target_ver.split('-')[0] + + arr_sver = sver.split('.') + arr_tver = tver.split('.') + + slen = arr_sver.length + tlen = arr_tver.length + len = tlen + + if slen > tlen then + gap = slen - tlen + gap.times do + arr_tver.push("0") + end + len = slen + elsif tlen > slen then + gap = tlen - slen + gap.times do + arr_sver.push("0") + end + len = tlen + end + + len.times do |i| + if arr_sver[i].to_i < arr_tver[i].to_i then + return 1 + elsif arr_sver[i].to_i > arr_tver[i].to_i then + return -1 + end + end + + return 0 + end + + + def Utils.generate_shell_command(cmd, os_category = nil) + if os_category.nil? then os_category = get_os_category( HOST_OS ) end + + if os_category == "windows" then mingw_path = "sh.exe -c " cmd = cmd.gsub("\"", "\\\"") - cmd = mingw_path + "\"#{cmd}\"" + cmd = mingw_path + "\"#{cmd}\"" end - system "#{cmd}" - if $?.to_i == 0 then ret = true else ret = false end - + return cmd + end + + + def Utils.execute_shell(cmd, os_category = nil) + ret = false + + # generate command + cmd = generate_shell_command(cmd, os_category) + + `#{cmd}` + if $?.to_i == 0 then ret = true else ret = false end + return ret end - def Utils.execute_shell_return(cmd) + def Utils.execute_shell_return(cmd, os_category = nil) result_lines = [] - if HOST_OS.eql? "windows" then - mingw_path = "sh.exe -c " - cmd = cmd.gsub("\"", "\\\"") - cmd = mingw_path + "\"#{cmd}\"" - end + # generate command + cmd = generate_shell_command(cmd, os_category) # get result - IO.popen("#{cmd} 2>&1") { |io| + IO.popen("#{cmd} 2>&1") do |io| io.each do |line| result_lines.push line end - } - - if $?.to_i == 0 then + end + + if $?.to_i == 0 then return result_lines - else + else return nil - end + end end - def Utils.execute_shell_return_ret(cmd) - if HOST_OS.eql? "windows" then - mingw_path = "sh.exe -c " - cmd = cmd.gsub("\"", "\\\"") - cmd = mingw_path + "\"#{cmd}\"" - end + def Utils.execute_shell_return_ret(cmd, os_category = nil) - return `#{cmd}` - end + # generate command + cmd = generate_shell_command(cmd, os_category) - def Utils.execute_shell_with_log(cmd, log) + return `#{cmd}` + end - if HOST_OS.eql? "windows" then - mingw_path = "sh.exe -c " + + # create process and log its all output(stderr, stdout) + # can decide whether wait or not + def Utils.execute_shell_with_log(cmd, log_path, wait=true) + + if log_path.nil? or log_path.empty? then + return execute_shell_with_stdout(cmd, nil) + end + + ruby_path=File.join(Config::CONFIG["bindir"], + Config::CONFIG["RUBY_INSTALL_NAME"] + + Config::CONFIG["EXEEXT"]) + + # call execute + os_category = get_os_category( HOST_OS ) + if os_category == "windows" then cmd = cmd.gsub("\"", "\\\"") - cmd = mingw_path + "\"#{cmd}\"" end + cmd = "#{ruby_path} \"#{File.expand_path(File.dirname(__FILE__))}/execute_with_log.rb\" \"#{cmd}\" \"#{log_path}\"" + + # print log + pipe = IO.popen("#{cmd} 2>&1") + if wait then + return Process.waitpid2(pipe.pid) + else + return [pipe.pid,nil] + end + end + + + def Utils.execute_shell_with_stdout(cmd, os_category = nil) + + logger = Logger.new(STDOUT) + + # generate command + cmd = generate_shell_command(cmd, os_category) + # print log - IO.popen("#{cmd} 2>&1") { |io| + pipe = IO.popen("#{cmd} 2>&1") do |io| io.each do |line| - log.output line + logger.info line end - } - - if $?.to_i == 0 then - return true - else - return false - end + end + + return [nil, nil] end + def Utils.spawn(cmd, os_category = nil) + + if os_category.nil? then os_category = get_os_category( HOST_OS ) end + + if os_category == "windows" then + create_process(cmd) + else + fork do + exec(cmd) + end + end + + end + + def Utils.create_process(command,redirStdout="", redirStderr="") + + if redirStdout.length > 0 + tmpfile = File.new(redirStdout,"w") + save_stdout = $stdout.clone + $stdout.reopen(tmpfile) + end + + if redirStderr.length > 0 + tmpfile = File.new(redirStderr,"w") + save_stderr = $stderr.clone + $stderr.reopen(tmpfile) + end + + params = [ + 'L', # IN LPCSTR lpApplicationName + 'P', # IN LPSTR lpCommandLine + 'L', # IN LPSECURITY_ATTRIBUTES lpProcessAttributes + 'L', # IN LPSECURITY_ATTRIBUTES lpThreadAttributes + 'L', # IN BOOL bInheritHandles + 'L', # IN DWORD dwCreationFlags + 'L', # IN LPVOID lpEnvironment + 'L', # IN LPCSTR lpCurrentDirectory + 'P', # IN LPSTARTUPINFOA lpStartupInfo + 'P' # OUT LPPROCESS_INFORMATION lpProcessInformation + ] + returnValue = 'I' # BOOL + + startupInfo = [STARTUP_INFO_SIZE].pack('I') + ([0].pack('I') * (STARTUP_INFO_SIZE - 4)) + processInfo = [0].pack('I') * PROCESS_INFO_SIZE + + createProcess = Win32API.new("kernel32", "CreateProcess", params, returnValue) + + createProcess.call(0, command, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, startupInfo, processInfo) + + if redirStdout.length > 0 + $stdout.reopen(save_stdout) + end + + save_stdout.close if save_stdout + + if redirStderr.length > 0 + $stderr.reopen(save_stderr) + end + + save_stderr.close if save_stderr + + ($0 == __FILE__ ) ? processInfo : processInfo.unpack("LLLL")[2] + end + def Utils.is_absolute_path(path) - if HOST_OS.eql? "linux" or HOST_OS.eql? "darwin" then + if is_unix_like_os( HOST_OS ) then # if path start "/" then absoulte path if path.start_with?("/") then return true else - return false + return false end - elsif HOST_OS.eql? "windows" then + elsif is_windows_like_os( HOST_OS ) then # if path start "c:/" or "D:/" or ... then absoulte path if path =~ /^[a-zA-Z]:[\/]/ then return true else return false end - else + else puts "HOST_OS is invalid" end end @@ -204,17 +330,313 @@ class Utils # this will be used on MinGW/MSYS def Utils.get_unix_path(path) - if HOST_OS.eql? "linux" or HOST_OS.eql? "darwin" then + if is_unix_like_os( HOST_OS ) then return path - elsif HOST_OS.eql? "windows" then + elsif is_windows_like_os( HOST_OS ) then new_path = path if is_absolute_path( new_path ) then new_path = "/" + new_path[0,1] + new_path[2..-1] end return new_path - else + else puts "HOST_OS is invalid" return path end end + + def Utils.file_lock(lock_file_name) + lock_file = File.new(lock_file_name, File::RDWR|File::CREAT, 0644) + lock_file.flock(File::LOCK_EX) + lock_file.rewind + lock_file.flush + lock_file.truncate(lock_file.pos) + + return lock_file + end + + def Utils.file_unlock(lock_file) + lock_file.close + end + + def Utils.parse_server_addr(saddr) + addr = saddr.split(":") + return nil unless addr.length == 2 + return addr + end + + def Utils.parse_ftpserver_url(surl) + return nil unless surl.start_with? "ftp://" + + surl = surl[6..-1] + parse1 = surl.split("@") + return nil unless parse1.length == 2 + + idpw = parse1[0] + url = parse1[1] + parse1 = idpw.split(":") + return nil unless parse1.length == 2 + + id = parse1[0] + passwd = parse1[1] + if url.end_with? "/" then url = url.chop end + + parse1 = url.split(":") + if parse1.length == 2 then + ip = parse1[0] + port = parse1[1] + elsif parse1.length == 1 then + ip = parse1[0] + port = 21 + else + return nil + end + + return [ip, port, id, passwd] + end + + + def Utils.generate_ftp_url(addr, port, username, passwd) + return "ftp://#{username}:#{passwd}@#{addr}:#{port}" + end + + + def Utils.extract_a_file(file_path, target_file, path) + dirname = File.dirname(file_path) + filename = File.basename(file_path) + ext = File.extname(filename) + + # path should be unix path if it is used in tar command + _package_file_path = Utils.get_unix_path(file_path) + _path = Utils.get_unix_path(path) + + case ext + when ".zip" then + if not path.nil? then + extract_file_command = "unzip -xo #{_package_file_path} #{target_file} -d #{_path}" + else + extract_file_command = "unzip -xo #{_package_file_path} #{target_file}" + end + when ".tar" then + if not path.nil? then + extract_file_command = "tar xf #{_package_file_path} -C #{_path} #{target_file}" + else + extract_file_command = "tar xf #{_package_file_path} #{target_file}" + end + end + + # check exit code + ret = execute_shell "#{extract_file_command}" + if not ret then return false end + + # check result file + if not path.nil? then + target_file_path = File.join(path, target_file) + else + target_file_path = target_file + end + + if not File.exist? target_file_path then + return false + else + return true + end + end + + + # check if the os is windows-like + def Utils.is_windows_like_os(os_name) + if os_name.start_with? "windows-" then + return true + else + return false + end + end + + + # check if the os is unix-like + def Utils.is_unix_like_os(os_name) + if os_name.start_with? "ubuntu-" or + os_name.start_with? "opensuse-" or + os_name.start_with?"macos-" then + return true + else + return false + end + end + + + # check if the os is linux-like + def Utils.is_linux_like_os(os_name) + if os_name.start_with? "ubuntu-" or + os_name.start_with? "opensuse-" then + return true + else + return false + end + end + + + # check if the os is macos-like + def Utils.is_macos_like_os(os_name) + if os_name.start_with?"macos-" then + return true + else + return false + end + end + + + def Utils.get_os_category(os_name) + if os_name.start_with? "ubuntu-" or os_name.start_with? "opensuse-" then + return "linux" + elsif os_name.start_with?"macos-" then + return "macos" + elsif os_name.start_with? "windows-" then + return "windows" + else + return os_name + end + end + + + def Utils.get_package_name_from_package_file( local_path ) + filename = File.basename(local_path) + if filename =~ /.*_.*_.*\.zip/ then + new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + return new_name.split(",")[0] + end + return nil + end + + + def Utils.get_version_from_package_file( local_path ) + filename = File.basename(local_path) + if filename =~ /.*_.*_.*\.zip/ then + new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + return new_name.split(",")[1] + end + return nil + end + + + def Utils.get_os_from_package_file( local_path ) + filename = File.basename(local_path) + if filename =~ /.*_.*_.*\.zip/ then + new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3') + return new_name.split(",")[2] + end + return nil + end + + def Utils.multi_argument_test( arg, seperator ) + return ( not arg.end_with? seperator and not arg.split( seperator ).select{|x| x.empty?}.length > 0 ) + end + + def Utils.directory_emtpy?(dir_path) + return (Dir.entries(dir_path).join == "...") + end + + + def Utils.checksum(file_path) + if File.exist? file_path then + return Utils.execute_shell_return("shasum -a 256 \"#{file_path}\"")[0].split(" ")[0] + else + return nil + end + end + + def Utils.get_version() + version_file = "#{File.dirname(__FILE__)}/../../VERSION" + + if not File.exist? version_file then + return nil + end + + f = File.open( version_file, "r" ) + version = f.readline + f.close + + return version + end + + + def Utils.kill_process(base_pid) + # stop process execution + # NOTE. On MinGW "STOP" option stop whole process, so don't use it + os_category = get_os_category(HOST_OS) + if os_category != "windows" then + Process.kill("STOP", base_pid) + end + + # get all sub processes # kill&wait + sub_pids = get_sub_processes(base_pid) + sub_pids.each do |pid| + Utils.kill_process(pid) + end + + begin + Process.kill(9, base_pid) + Process.waitpid2(base_pid) + rescue + # do nothing + end + end + + + def Utils.get_sub_processes(base) + result = [] + + # generate pid => ppid hash + # NOTE. MinGW does not support "-o" option and has different output format + os_category = get_os_category(HOST_OS) + if os_category != "windows" then + Hash[*`ps -eo pid,ppid`.scan(/\d+/).map{|x| x.to_i}].each do |pid,ppid| + if ppid == base then + result.push pid + end + end + else + # NOTE.On windows, there two types of pid. win pid, mingw pid + # Sometime these different pids has same value with difference process + # Root of pid is win pid and leaf node is mingw pid + # So, after we get mingw pid, win pid should not be checked. + # gather MinGW/MSYS process id + Hash[*`ps -e`.scan(/^[\s]*(\d+)[\s]+(\d+)/).flatten.map{|x| x.to_i}].each do |pid,ppid| + if ppid == base then + result.push pid + end + end + + # gather windows process id if no mingw pid + if result.count == 0 then + require 'rubygems' + require 'sys/proctable' + Sys::ProcTable.ps do |proc| + if proc.ppid == base then + result.push proc.pid + end + end + end + end + + result.uniq! + return result + end + + + + if defined?(HOST_OS).nil? then + HOST_OS = Utils.identify_current_OS() + end + + # set static variable in WORKING_DIR, HOME + if defined?(WORKING_DIR).nil? then WORKING_DIR = Dir.pwd end + if defined?(HOME).nil? then + # get home directory, using Dir.chdir + Dir.chdir + HOME = Dir.pwd + Dir.chdir WORKING_DIR + end + + end diff --git a/src/pkg_server/DistSync.rb b/src/pkg_server/DistSync.rb new file mode 100644 index 0000000..a79ea4b --- /dev/null +++ b/src/pkg_server/DistSync.rb @@ -0,0 +1,97 @@ +=begin + + DistSync.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require "fileutils" +require "thread" +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "Action.rb" +require "ScheduledActionHandler.rb" + +class DistSyncAction < Action + + def initialize(time, pkgserver, dist_name ) + super(time, pkgserver.sync_interval) + + @pkgserver = pkgserver + @dist_name = dist_name + end + + + def init + end + + + def execute + # Start to sync job + @pkgserver.log.info "Executing sync action for the #{@dist_name}" + begin + execute_internal() + rescue => e + @pkgserver.log.error e.message + @pkgserver.log.error e.backtrace.inspect + end + end + + + private + def execute_internal() + # update pkg info + @pkgserver.reload_dist_package + + # sync + @pkgserver.sync( @dist_name, false ) + end +end + + +class DistSync + attr_accessor :quit + + # init + def initialize( server ) + @server = server + @handler = ScheduledActionHandler.new + end + + # start thread + def start() + # scan all sync distribution + @server.distribution_list.each do |dist| + # if dist does not have parent server then skip sync + if dist.server_url.empty? then next end + + time = Time.now + @server.log.info "Registered sync-action for dist : #{dist.name}" + @handler.register(DistSyncAction.new(time, @server, dist.name)) + end + + # start handler + @handler.start + end +end diff --git a/src/pkg_server/SocketRegisterListener.rb b/src/pkg_server/SocketRegisterListener.rb new file mode 100644 index 0000000..9982274 --- /dev/null +++ b/src/pkg_server/SocketRegisterListener.rb @@ -0,0 +1,240 @@ +=begin + + SocketRegisterListener.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'socket' +require 'thread' +$LOAD_PATH.unshift File.dirname(__FILE__) +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/build_server" +require "packageServerConfig" +require "BuildComm" +require "net/ftp" + +# mutax for register operation +$register_mutex = Mutex.new + +class SocketRegisterListener + + # initialize + def initialize (parent) + @parent_server = parent + @thread = nil + @finish_loop = false + @log = @parent_server.log + end + + # start listening + def start() + @log.info "SocketRegisterListener start" + @thread = Thread.new do + main() + end + end + + # quit listening + def stop_listening() + @finish_loop = true + end + + private + + # thread main + def main() + @log.info "SocketRegisterListener entering main loop" + # server open + begin + @comm_server = BuildCommServer.create(@parent_server.port, @log) + rescue => e + @log.info "Server creation failed" + @log.error e.message + @log.error e.backtrace.inspect + return + end + + # loop + @log.info "Entering Control Listening Loop ... " + @finish_loop = false + @comm_server.wait_for_connection(@finish_loop) do |req| + begin + handle_job_request( req ) + rescue => e + @log.info "error occured in handle_job_request function" + @log.error e.message + @log.error e.backtrace.inspect + end + end + + # quit + @comm_server.terminate + end + + # wait for job requests + def wait_for_job_requests + req_list = [] + req_list.push @tcp_server.accept + + return req_list + end + + # handle job request + def handle_job_request( req ) + + # read request + req_line = req.gets + if req_line.nil? then return end + + # parse request + cmd = "" + if req_line.split("|").count > 0 then + cmd = req_line.split("|")[0].strip + end + + case cmd + when "UPLOAD" + Thread.new do + handle_cmd_upload( req_line, req ) + end + when "REGISTER" + Thread.new do + handle_cmd_register( req_line, req ) + end + when "STOP" + handle_cmd_stop( req_line, req ) + else + @log.error "Received Unknown REQ: #{req_line}" + end + @log.info "REQ processing done" + end + + # "UPLOAD" + def handle_cmd_upload( line, req ) + @log.info "Received File transfer REQ : #{line}" + + BuildCommServer.send_begin(req) + + tok = line.split("|").map { |x| x.strip } + if tok.count > 1 then + dock_name = tok[1].strip + incoming_dir = "#{@parent_server.incoming_path}/#{dock_name}" + FileUtils.mkdir_p(incoming_dir) + else + incoming_dir = "#{@parent_server.incoming_path}" + end + + file_path_list = [] + begin + @comm_server.receive_file(req, incoming_dir) + rescue => e + @log.error "Failed to transfer file" + @log.error e.message + @log.error e.backtrace.inspect + end + BuildCommServer.send_end(req) + end + + # "Register" + def handle_cmd_register( line, req ) + @log.info "Received register REQ : #{line}" + BuildCommServer.send_begin(req) + + tok = line.split("|").map { |x| x.strip } + if tok.count < 3 then + @log.error "Received Wrong REQ : #{line}" + BuildCommServer.send(req, "ERROR|Invalid REQ format") + return + end + dist_name = tok[1].strip + + if tok[2].start_with? "DOCK" then + dock_name = tok[3] + idx = 4 + else + dock_name = "" + idx = 2 + end + + file_path_list = [] + + while idx < tok.length do + if dock_name.empty? then + file_path_list.push "#{@parent_server.incoming_path}/#{tok[idx]}" + else + file_path_list.push "#{@parent_server.incoming_path}/#{dock_name}/#{tok[idx]}" + end + idx = idx + 1 + end + # register mutex + $register_mutex.synchronize do + begin + @parent_server.reload_dist_package() + snapshot_name = @parent_server.register( file_path_list, dist_name, true, false, true) + BuildCommServer.send(req,"SUCC|#{snapshot_name}") + rescue => e + @log.error "register failed" + @log.error e.message + @log.error e.backtrace.inspect + BuildCommServer.send(req, "ERROR|#{e.message}") + @parent_server.release_lock_file + return + end + end + + if not dock_name.empty? then + FileUtils.rm_rf "#{@parent_server.incoming_path}/#{dock_name}" + end + + BuildCommServer.send_end(req) + end + + # "STOP" + def handle_cmd_stop( line, req ) + @log.info "Received STOP REQ" + + BuildCommServer.send_begin(req) + + tok = line.split("|").map { |x| x.strip } + if tok.count < 2 then + @log.error "Received Wrong REQ : #{line}" + BuildCommServer.send(req, "ERROR|Invalid REQ format") + return + end + passwd = tok[1].strip + + if @parent_server.passwd.eql? passwd then + @parent_server.finish = true + @log.info "Package server stop flag set" + BuildCommServer.send(req,"SUCC") + else + @log.info "Received stop command, but passwd mismatched : #{passwd}" + BuildCommServer.send(req,"ERROR|Password mismatched!") + end + BuildCommServer.send_end(req) + BuildCommServer.disconnect(req) + end +end + diff --git a/src/pkg_server/client.rb b/src/pkg_server/client.rb index 8bffbd2..a3e3815 100644 --- a/src/pkg_server/client.rb +++ b/src/pkg_server/client.rb @@ -1,7 +1,6 @@ - =begin - - client.rb + + client.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -28,1445 +27,1714 @@ Contributors: =end require "fileutils" +require "thread" +require "net/ftp" $LOAD_PATH.unshift File.dirname(__FILE__) $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/build_server" require "downloader" require "installer" -require "serverConfig" +require "packageServerConfig" require "package" require "parser" require "utils" require "log" require "Version" +require "BuildComm" +require "FileTransferViaFTP" +require "FileTransferViaDirect" + +$update_mutex = Mutex.new +$get_snapshot_mutex = Mutex.new +$filemove_mutex = Mutex.new class Client - # constant - SUPPORTED_OS = ["linux", "windows", "darwin"] - PKG_LIST_FILE_PREFIX = "pkg_list_" - INSTALLED_PKG_LIST_FILE = "installedpackage.list" - CONFIG_PATH = "#{$build_tools}/client" - PACKAGE_INFO_DIR = ".info" - DEFAULT_INSTALL_DIR = "#{Utils::HOME}/build_root" - DEFAULT_SERVER_ADDR = "http://172.21.17.55/dibs/unstable" - - attr_accessor :server_addr, :location, :pkg_hash_os, :is_server_remote, :installed_pkg_hash_loc, :archive_pkg_list, :all_dep_list, :log - - public - # initialize - # create "remote package hash" and "installed package hash" - # @server_addr = server address (can be included distribution, snapshot) - # @location = client location (download and install file to this location) - def initialize(server_addr, location, logger) - - # create directory + # constant + PKG_LIST_FILE_PREFIX = "pkg_list_" + INSTALLED_PKG_LIST_FILE = "installedpackage.list" + CONFIG_PATH = "#{PackageServerConfig::CONFIG_ROOT}/client" + PACKAGE_INFO_DIR = ".info" + DEFAULT_INSTALL_DIR = "#{Utils::HOME}/build_root" + DEFAULT_SERVER_ADDR = "http://172.21.17.55/dibs/unstable" + OS_INFO_FILE = "os_info" + ARCHIVE_PKG_LIST_FILE = "archive_pkg_list" + + attr_accessor :server_addr, :location, :pkg_hash_os, :is_server_remote, :installed_pkg_hash_loc, :archive_pkg_list, :all_dep_list, :log, :support_os_list, :config_dist_path, :download_path, :tmp_path, :snapshot_path, :snapshots_path, :snapshot_url + + public + # initialize + # create "remote package hash" and "installed package hash" + # @server_addr = server address (can be included distribution, snapshot) + # @location = client location (download and install file to this location) + def initialize(server_addr, location, logger) + + # set log + if logger.nil? or logger.class.to_s.eql? "String" then + @log = DummyLog.new() + else + @log = logger + end + + # create directory if not File.exist? CONFIG_PATH then FileUtils.mkdir_p "#{CONFIG_PATH}" end - # set default server address, location - if server_addr.nil? then server_addr = get_default_server_addr() end - if location.nil? then location = get_default_inst_dir() end - - # chop server address, if end with "/" - if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end - - @server_addr = server_addr - @location = location - @pkg_hash_os = {} - @installed_pkg_hash_loc = {} - @archive_pkg_list = [] - @all_dep_list = [] - @is_server_remote = Utils.is_url_remote(server_addr) - - # set log - if logger.nil? or logger.class.to_s.eql? "String" then - @log = Log.new(logger) - else - @log = logger - end - - FileInstaller.set_logger(@log) - FileDownLoader.set_logger(@log) - - # read installed pkg list, and create hash - FileUtils.mkdir_p "#{@location}" - create_installed_pkg_hash() - - # readk remote pkg list, and hash list - create_remote_pkg_hash(false) - @log.info "Initialize - #{server_addr}, #{location}" - end - - public - # update package list from server - def update() - if not create_remote_pkg_hash(true) then - @log.error "\"#{@server_addr}\" does not have package list file properly." - return false - end - create_default_config(@server_addr) - @log.info "Update package list from \"#{@server_addr}\".. OK" - return true - end - - public - # download package - def download(pkg_name, os, trace) - - dependent_pkg_list = [] - - # get dependent list - if trace then - dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, false) - if dependent_pkg_list.nil? then - @log.error "Failed to get dependency for \"#{pkg_name}\" package" - return false - end - else dependent_pkg_list = [pkg_name] end - - surl = nil - addr_arr = @server_addr.split('/') - if addr_arr[-2].eql? "snapshots" then - surl = @server_addr + "/../.." - else - surl = @server_addr - end - - # download files - file_local_path = [] - dependent_pkg_list.each do |p| - pkg_path = get_attr_from_pkg(p, os, "path") - pkg_ver = get_attr_from_pkg(p, os, "version") - url = surl + pkg_path - filename = pkg_path.split('/')[-1] - if not FileDownLoader.download(url, @location) then - @log.error "Failed download #{pkg_name} [#{pkg_ver}]" - return nil - end - - file_local_path.push(File.join(@location, filename)) - @log.info "Downloaded \"#{pkg_name} [#{pkg_ver}]\" package file.. OK" - @log.info " [path : #{file_local_path.join(", ")}]" - end - - return file_local_path - end - - public - # download source package - def download_source(pkg_name, os) - - # get source file path - src_path = get_attr_from_pkg(pkg_name, os, "src_path") - if src_path.nil? or src_path.empty? then - @log.error "#{pkg_name} package does not have source" - return nil - end - file_url = nil - - addr_arr = @server_addr.split('/') - if addr_arr[-2].eql? "snapshots" then - surl = @server_addr + "/../.." + src_path - else - surl = @server_addr + src_path - end - - # download file - filename = src_path.split('/')[-1] - if not FileDownLoader.download(surl, @location) then - @log.error "Failed download #{pkg_name} source" - return nil - end - file_local_path = File.join(@location, filename) - @log.info "Downloaded source of #{pkg_name} package.. OK" - @log.info " [path : #{file_local_path}]" - - return file_local_path - end - - public - # download dependent source - def download_dep_source(file_name) - - file_url = nil - - addr_arr = @server_addr.split('/') - if addr_arr[-2].eql? "snapshots" then - file_url = @server_addr + "/../../source/" + file_name - else - file_url = @server_addr + "/source/#{file_name}" - end - if not FileDownLoader.download(file_url, @location) then - @log.error "Failed download #{file_name}" - return nil - end - file_local_path = File.join(@location, file_name) - @log.info "Downloaded \"#{file_name}\" source file.. OK" - @log.info " [path : #{file_local_path}]" - - return file_local_path - end - - public - # check archive file - def check_archive_file(file_name) - - result = false - filename = "archive_pkg_list" - local_file_path = File.join(CONFIG_PATH, filename) - if File.exist? local_file_path then - File.open(local_file_path, "r") do |f| - f.each_line do |l| - if l.strip.eql? file_name.strip then - result = true - break - end - end - end - end - return result - end - - public - # upload package - def upload(ssh_alias, id, binary_path_list, source_path_list, verify) - - # check source path list - if source_path_list.nil? or source_path_list.empty? then - @log.error "source package path should be set." - return nil - end - - # verify ssh alias - verify = false - hostfound = false - sshconfig = "#{Utils::HOME}/.ssh/config" - File.open(sshconfig, "r") do |f| - f.each_line do |l| - if l.strip.upcase.start_with? "HOST" then - al = l.strip.split(' ')[1].strip - if al.eql? ssh_alias then hostfound = true - else next end - end - end - end - - if not hostfound then - @log.error "\"#{ssh_alias}\" does not exist in \".ssh/config\" file" - return nil - end - - # get distribution from server addr - dist = get_distribution() - if dist.nil? then - @log.error "Distribution is nil" - return nil - end - - serveraddr = @server_addr - snapshot = nil - if serveraddr.include? "snapshots" then snapshot = serveraddr.split("/")[-1] end - - # set server homd directory - server_home = `ssh #{ssh_alias} pwd` - server_home = server_home.strip - - # set "pkg-svr" file path - # if pkg-svr exist in path then using pkg-svr - result = `ssh #{ssh_alias} which pkg-svr` - if not( result.nil? or result.empty? or result.strip.empty? ) then - pkg_svr = "pkg-svr" + # set default server address, location + if server_addr.nil? then server_addr = get_default_server_addr() end + if location.nil? then location = get_default_inst_dir() end + + # chop server address, if end with "/" + if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end + + @snapshot_path = nil + @snapshot_url = false + + if is_snapshot_url(server_addr) then + @snapshot_url = true + @server_addr, @snapshot_path = split_addr_and_snapshot(server_addr) + else + @server_addr = server_addr + end + + @location = location + @pkg_hash_os = {} + @installed_pkg_hash_loc = {} + @archive_pkg_list = [] + @all_dep_list = [] + @is_server_remote = Utils.is_url_remote(server_addr) + @support_os_list = [] + @config_dist_path = CONFIG_PATH + "/" + get_flat_serveraddr + @download_path = @config_dist_path + "/downloads" + @tmp_path = @config_dist_path + "/tmp" + @snapshots_path = @config_dist_path + "/snapshots" + + # create directory + if not File.exist? @config_dist_path then FileUtils.mkdir_p "#{@config_dist_path}" end + if not File.exist? @download_path then FileUtils.mkdir_p "#{@download_path}" end + if not File.exist? @snapshots_path then FileUtils.mkdir_p "#{@snapshots_path}" end + if not File.exist? @tmp_path then FileUtils.mkdir_p "#{@tmp_path}" end + + # read installed pkg list, and create hash + if not File.exist? @location then FileUtils.mkdir_p "#{@location}" end + @log.info "Update local package list.. [#{@location}]" + read_installed_pkg_list() + + # read remote pkg list, and hash list + @log.info "Update remote package list and supported os list.." + update() + @log.info "Initialize - #{server_addr}, #{location}" + end + + public + # update package list from server + def update() + if not @snapshot_url then + $get_snapshot_mutex.synchronize do + @snapshot_path = get_lastest_snapshot(@is_server_remote) + end + end + @log.info "The lastest snapshot : #{@snapshot_path}" + if @snapshot_path.nil? then + @log.warn "Failed to get the lastest package list" + @snapshot_path = "" + end + + exists_snapshot = false + if is_snapshot_exist(@snapshot_path) then + @log.info "Snapshot information is already cached [#{get_pkglist_path()}]" + exists_snapshot = true + else + @log.info "Snapshot information is not cached" + end + + list_path = get_pkglist_path() + if list_path.nil? then + @log.error "Failed to get package list path" + return false + end + + clean_list() + + if exists_snapshot then + read_supported_os_list(list_path) + read_remote_pkg_list(list_path) + read_archive_pkg_list(list_path) + else + $update_mutex.synchronize do + uniq_name = Utils.create_uniq_name + tmp_dir = File.join(@config_dist_path, uniq_name) + FileUtils.mkdir_p tmp_dir + if not download_os_list(@is_server_remote, tmp_dir) then + @log.error "\"#{@server_addr}\" does not have supported os list file properly." + Utils.execute_shell("rm -rf #{tmp_dir}") + return false + else read_supported_os_list(tmp_dir) end + + if not download_pkg_list(@is_server_remote, tmp_dir) then + @log.error "\"#{@server_addr}\" does not have package list file properly." + Utils.execute_shell("rm -rf #{tmp_dir}") + return false + else read_remote_pkg_list(tmp_dir) end + + if not download_archive_pkg_list(@is_server_remote, tmp_dir) then + @log.error "\"#{@server_addr}\" does not have archive package list file properly. This error can be ignored" + else read_archive_pkg_list(tmp_dir) end + Utils.execute_shell("mv #{tmp_dir} #{list_path}") + @log.info "Moved \"#{tmp_dir}\" to" + @log.info " \"#{list_path}\"" + # tmp_dir should be removed whether mv command is failed + Utils.execute_shell("rm -rf #{tmp_dir}") + remove_snapshots() + end + end + + $update_mutex.synchronize do + create_default_config(@server_addr) + @log.info "Update package list from \"#{@server_addr}\".. OK" + end + + return true + end + + private + def clean_list() + @pkg_hash_os.clear + @archive_pkg_list.clear + @support_os_list.clear + @log.info "Cleard package list, supported os list.. OK" + end + + public + # download package + def download(pkg_name, os, trace, loc = nil) + + if loc.nil? then loc = @location end + + if not File.exist? loc then FileUtils.mkdir_p "#{loc}" end + + dependent_pkg_list = [] + + # get dependent list + if trace then + dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, true) + if dependent_pkg_list.nil? then + @log.error "Failed to get dependency for \"#{pkg_name}\" package" + return nil + end + else dependent_pkg_list = [pkg_name] end + + surl = @server_addr + # download files + file_local_path = [] + dependent_pkg_list.each do |p| + pkg_name = get_attr_from_pkg(p, os, "name") + pkg_path = get_attr_from_pkg(p, os, "path") + pkg_ver = get_attr_from_pkg(p, os, "version") + pkg_checksum = get_attr_from_pkg(p, os, "checksum") + pkg_size = get_attr_from_pkg(p, os, "size") + if pkg_path.nil? or pkg_ver.nil? then + @log.error "\"#{p}\" package does not exist in package server. If it exist in package server, then try \"pkg-cli update\"" + return nil + end + url = surl + pkg_path + filename = pkg_path.split('/')[-1] + + if not FileDownLoader.download(url, loc, @log) then + @log.error "File Download Failed!!" + @log.error "* #{url} -> #{loc}" + return nil + end + + file_path = File.join(loc, filename) + file_local_path.push(file_path) + end + + if trace then + @log.info "Downloaded \"#{pkg_name}\" package with all dependent packages.. OK" + end + @log.info " [path: #{file_local_path.join(", ")}]" + + return file_local_path + end + + private + def remove_downloaded_pkgs(pkg_name, os) + pkg_file_prefix = "#{@download_path}/#{pkg_name}_*_#{os}.zip" + pkg_files = Dir[pkg_file_prefix].sort_by { |f| File.mtime(f) }.reverse + + if not pkg_files.nil? and pkg_files.length >= 4 then + Utils.execute_shell("rm -rf #{pkg_files[3..-1].join(" ")}") + @log.info "Removed old package files.." + @log.info " * #{pkg_files[3..-1].join(", ")}" + end + end + + private + def move_downloaded_pkg(filepath, distpath) + if filepath.nil? or filepath == "" then return nil end + filename = filepath.split('/')[-1] + if not File.exist? distpath then FileUtils.mkdir_p "#{distpath}" end + distfile = File.join(distpath, filename) + @log.info "Moving \"#{filename}\" to download cache directory" + @log.info " [path: #{distpath}]" + $filemove_mutex.synchronize do + if not File.exist? distfile then + Utils.execute_shell("mv #{filepath} #{distfile}") + else + Utils.execute_shell("rm -f #{filepath}") + return distfile + end + end + + if File.exist? distfile then return distfile else - # if pkg-svr not exist in path then try ~/tizen_sdk/dev_tools/pkg-svr - result = `ssh #{ssh_alias} which #{server_home}/tizen_sdk/dev_tools/pkg-svr` - if not( result.nil? or result.empty? or result.strip.empty? ) then - pkg_svr = "#{server_home}/tizen_sdk/dev_tools/pkg-svr" - else - @log.error "Can't find server's pkg-svr command" - return nil + @log.info "Failed to move [#{filenamae}] to " + @log.info " [#{distpath}]" + return nil + end + end + + private + def remove_snapshots() + listing_prefix = "#{@snapshots_path}/*" + dirs = Dir[listing_prefix].sort_by { |f| File.mtime(f) }.reverse + + if not dirs.nil? and dirs.length >= 20 then + Utils.execute_shell("rm -rf #{dirs[19..-1].join(" ")}") + @log.info "Removed old snapshots.." + @log.info " * #{dirs[19]} ~ " + end + end + + private + def get_cached_filepath(pkg_filename, pkg_checksum, pkg_size) + + cached_filepath = "#{@download_path}/#{pkg_filename}" + if File.exist? cached_filepath then + checksum = `sha256sum #{cached_filepath}`.split(" ")[0] + size = `du -b #{cached_filepath}`.split[0].strip + if checksum.eql? pkg_checksum and size.eql? pkg_size then + return cached_filepath + end + end + return nil + end + + public + # download dependent source + def download_dep_source(file_name) + + file_url = @server_addr + "/source/#{file_name}" + if not FileDownLoader.download(file_url, @location, @log) then + @log.error "Failed download #{file_name}" + return nil + end + file_local_path = File.join(@location, file_name) + @log.info "Downloaded \"#{file_name}\" source file.. OK" + @log.info " [path: #{file_local_path}]" + + return file_local_path + end + + public + # upload package + def upload(ip, port, binary_path_list, ftp_addr=nil, ftp_port=nil, ftp_username=nil, ftp_passwd=nil) + + # check ip and port + if ip.nil? or port.nil? then + @log.error "Ip and port should be set." + return nil + end + + # check binary path list + if binary_path_list.nil? or binary_path_list.empty? then + @log.error "Binary package path should be set." + return nil + end + + # create unique dock number + dock = Utils.create_uniq_name() + + # upload file + binary_list = [] + binary_path_list.each do |bpath| + filename = File.basename(bpath) + client = BuildCommClient.create(ip, port, @log) + + if client.nil? then + @log.error "Failed to create BuildCommClient instance.." + return nil + end + + @log.info "Send ready REQ.. [UPLOAD]" + result = client.send("UPLOAD|#{dock}") + if not result then + @log.error "Failed to send ready REQ.." + return nil + end + + begin + if not ftp_addr.nil? then + transporter=FileTransferFTP.new(@log, ftp_addr, ftp_port, ftp_username, ftp_passwd) + else + transporter=FileTransferDirect.new(@log) + end + + result = client.send_file(bpath, transporter) + rescue => e + @log.error "FTP failed to put file (exception)" + @log.error "#{e.message}" + @log.error e.backtrace.inspect + return nil + end + + if not result then + @log.error "FTP failed to put file (result is false)" + return nil + end + + client.terminate + binary_list.push(filename) + end + + # register file + if not binary_list.empty? then + client = BuildCommClient.create(ip, port, @log) + dist = get_distribution + if dist.empty? then + @log.error "Distribution is empty.." + return nil + end + + @log.info "Send register message.. [REGISTER|#{dist}|DOCK|#{dock}|#{binary_list.join("|")}]" + snapshot = nil + if client.send "REGISTER|#{dist}|DOCK|#{dock}|#{binary_list.join("|")}" then + result = client.read_lines do |l| + line = l.split("|") + if line[0].strip == "ERROR" then + @log.error l.strip + break + elsif line[0].strip == "SUCC" then + snapshot = line[1].strip + end + end + + if not result or snapshot.nil? then + @log.error "Failed to register! #{client.get_error_msg()}" + return nil + end + end + + client.terminate + snapshot = @server_addr + "/snapshots/" + snapshot + @log.info "Registered successfully! [#{binary_path_list.join("|")}]" + if snapshot.empty? then + @log.error "Failed to generate snapshot" + end + end + + return snapshot + end + + private + # verify package before uploading + def verify_upload(pkg_name, pkg_path) + + manifest_file = "pkginfo.manifest" + uniq_name = Utils.create_uniq_name + path = Utils::HOME + "/tmp/#{uniq_name}" + if not File.exist? path then FileUtils.mkdir_p "#{path}" end + begin + if not FileInstaller.extract_a_file(pkg_path, manifest_file, path, @log) then + @log.error "The \"pkginfo.manifest\" file does not exist in \"#{pkg_path}\"" + return false + end + manifest_path = File.join(path, manifest_file) + pkg = Parser.read_single_pkginfo_from manifest_path + if File.exists? manifest_path then FileUtils.rm_f(manifest_path) end + FileUtils.remove_dir(path, true) + rescue Interrupt + @log.error "Client: Interrupted.." + FileUtils.remove_dir(path, true) + @log.info "Removed #{path}" + raise Interrupt + rescue RuntimeError => e + @log.error( e.message, Log::LV_USER) + FileUtils.remove_dir(path, true) + @log.info "Removed #{path}" + return false + end + new_pkg_ver = pkg.version + new_pkg_install_dep_list = pkg.install_dep_list + os = pkg.os + + list = get_all_reverse_install_dependent_packages_remote(pkg_name, os, true) + + if not list.nil? then + list.each do |p| + ilist = get_attr_from_pkg(p, os, "install_dep_list") + if ilist.nil? then next end + ilist.each do |l| + if l.package_name.eql? pkg_name then + if not l.match? new_pkg_ver then + @log.error "\"#{p}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})" + return false + end + end + end + end + end + + if not new_pkg_install_dep_list.nil? then + new_pkg_install_dep_list.each do |l| + if not check_remote_pkg(l.package_name, os) then + @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version}), but \"#{l.package_name}\" is not exist on server" + return false + end + rver = get_attr_from_pkg(l.package_name, os, "version") + if not l.match? rver then + @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})" + return false + end end - end - pkg_svr = "#{server_home}/tizen_sdk/dev_tools/pkg-svr" - - # set incoming directory (~/.build_tools/pkg_server/#{id}/incoming) - incoming_path = "#{server_home}/.build_tools/pkg_server/#{id}/incoming" - - # set pkg-svr register command - register_command = "#{pkg_svr} register -i #{id} -d #{dist}" - - # upload source package (scp) - server_src_pkg_list_command = "\"" - source_path_list.each do |spath| - # set source package file path for server filesystem - src_file_name = File.basename(spath) - server_src_pkg_path = "#{incoming_path}/#{src_file_name}" - server_src_pkg_list_command = server_src_pkg_list_command + server_src_pkg_path + "," - # upload source package - if File.exist? spath then - system "scp #{spath} #{ssh_alias}:#{server_src_pkg_path}" - else - @log.error "#{spath} file does not exist" - return nil - end - end - - server_src_pkg_list_command = server_src_pkg_list_command.strip - if server_src_pkg_list_command.end_with? "," then - server_src_pkg_list_command = server_src_pkg_list_command.chop + "\"" - else - server_src_pkg_list_command = server_src_pkg_list_command + "\"" - end - - # add src package list to register command - register_command = register_command + " -s #{server_src_pkg_list_command} -g" - - # upload binary package (scp) - if not binary_path_list.nil? then - server_bin_pkg_list_command = "\"" - binary_path_list.each do |bpath| - bin_file_name = File.basename(bpath) - bin_pkg_name = bin_file_name.split("_")[0] - if verify then - if not verify_upload(bin_pkg_name, bpath) then - @log.error "Failed to verify \"#{bpath}\" file" - return nil - end - end - - server_bin_pkg_path = "#{incoming_path}/#{bin_file_name}" - server_bin_pkg_list_command = server_bin_pkg_list_command + server_bin_pkg_path + "," - # upload binary package - if File.exist? bpath then - Utils.execute_shell("cd #{File.dirname(bpath)};scp #{File.basename(bpath)} #{ssh_alias}:#{server_bin_pkg_path}") - else - @log.error "#{bpath} file does not exist" - return nil - end - end - - server_bin_pkg_list_command = server_bin_pkg_list_command.strip - if server_bin_pkg_list_command.end_with? "," then - server_bin_pkg_list_command = server_bin_pkg_list_command.chop + "\"" - else - server_bin_pkg_list_command = server_bin_pkg_list_command + "\"" - end - - # add bin package list to register command - register_command = register_command + " -p #{server_bin_pkg_list_command}" - end - - @log.info "register_command : #{register_command}" - - # register packages to server - result = `ssh #{ssh_alias} #{register_command}` - if result.strip.include? "Error occured" then - puts result - return nil - end - - # parsing snapshot url to show user - serveraddr = @server_addr - arr = serveraddr.split("/") - if serveraddr.include? "snapshots" then sid = arr[-4] - else sid = arr[-2] end - i = serveraddr.index(sid) - serveraddr = serveraddr[0..i-1] - serveraddr = serveraddr + id + "/" + dist - - addr = [] - result2 = "" - arr_re = result.split("\n") - arr_re.each do |l| - l = l.strip - if l.start_with? "snapshot is generated :" then - addr = l.split(":")[1].split("/") - if addr.include? dist then - i = addr.index(dist) - addr = addr[i+1..-1] - str = "" - addr.each do |l| str = str + "/" + l end - str = serveraddr.strip + str - result2 = result2 + str +"\n" - end - end - end - - @log.info "Upload packages.. OK" - @log.info " [#{binary_path_list.join(", ")}]" - @log.info " [#{source_path_list.join(", ")}]" - return result2 - end - - private - # verify package before uploading - def verify_upload(pkg_name, pkg_path) - - manifest_file = "pkginfo.manifest" - uniq_name = Utils.create_uniq_name - path = Utils::HOME + "/tmp/#{uniq_name}" - FileUtils.mkdir_p "#{path}" - if not FileInstaller.extract_specified_file(pkg_path, manifest_file, path) then - @log.error "The \"pkginfo.manifest\" file does not exist in \"#{pkg_path}\"" - return false - end - manifest_path = File.join(path, manifest_file) - pkg_hash = Parser.read_pkg_list(manifest_path) - FileUtils.rm_f(manifest_path) - FileUtils.remove_dir(path, true) - - new_pkg_ver = pkg_hash[pkg_name].version - new_pkg_install_dep_list = pkg_hash[pkg_name].install_dep_list - os = pkg_hash[pkg_name].os - - list = get_all_reverse_install_dependent_packages_remote(pkg_name, os, true) - - if not list.nil? then - list.each do |p| - ilist = get_attr_from_pkg(p, os, "install_dep_list") - if ilist.nil? then next end - ilist.each do |l| - if l.package_name.eql? pkg_name then - if not l.match? new_pkg_ver then - @log.error "\"#{p}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})" - return false - end - end - end - end - end - - if not new_pkg_install_dep_list.nil? then - new_pkg_install_dep_list.each do |l| - if not check_remote_pkg(l.package_name, os) then - @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version}), but \"#{l.package_name}\" is not exist on server" - return false - end - rver = get_attr_from_pkg(l.package_name, os, "version") - if not l.match? rver then - @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})" - return false - end - end - end - - @log.info "Passed to verify packages for uploading.. OK" - return true - end - - private - # get distribution - def get_distribution() - server = @server_addr - if server.nil? or server.empty? then - @log.error "Server addr is nil" - return nil - end - - dist = "" - server_arr = server.split("/") - if server_arr.include? "snapshots" then - i = server_arr.index("snapshots") - dist = server_arr[i-1] - else dist = File.basename(server) end - - return dist - end - - public + end + + @log.info "Passed to verify packages for uploading.. OK" + return true + end + + private + # get distribution + def get_distribution() + server = @server_addr + if server.nil? or server.empty? then + @log.error "Server addr is nil" + return nil + end + + dist = "" + dist = File.basename(server) + + return dist + end + + private + def get_flat_serveraddr() + server = @server_addr + if server.nil? or server.empty? then + @log.error "Server addr is nil" + @log.error "check sync_pkg_servers table pkgsvr_url column is null" + return "nil" + end + + server = server.delete ".:/@" + return server + end + + public # install package - # install all install dependency packages - def install(pkg_name, os, trace, force) - - if trace.nil? then trace = true end - if force.nil? then force = false end - - # check meta package - is_meta_pkg = check_meta_pkg(pkg_name, os) - if is_meta_pkg then trace = true end - - pkg_ver = get_attr_from_pkg(pkg_name, os, "version") - if pkg_ver.nil? or pkg_ver.empty? then - @log.error "#{pkg_name} package does not exist in remote package list" - return false - end - - compare_result = compare_version_with_installed_pkg(pkg_name, pkg_ver) - if not force then - case compare_result - when -1 then - @log.warn "\"#{pkg_name}\" package version is bigger then remote package version" - return true - when 0 then - @log.warn "\"#{pkg_name}\" package version is same with remote package version" - return true - when 1, 2 then - end - end - - # if enable trace, crate all dependent package list - if trace then - dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, force) - if dependent_pkg_list.nil? then - @log.error "Failed to get dependency for \"#{pkg_name}\" package" - return false - end - else - dependent_pkg_list = [pkg_name] - end - - # if meta package, dependent list does not need to include self name - #if is_meta_pkg then - # dependent_pkg_list.delete(pkg_name.strip) - #end - - # TODO: need to compare dependent package version - # install packages including dependent packages - dependent_pkg_list.each do |pkg| - if not install_pkg(pkg, os, force) then - @log.error "#{pkg} does not exist" - return false - end - add_pkg_info(pkg, os) - end - write_pkg_hash_to_file(nil) - - if trace then - @log.info "Installed \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK" - @log.info " [#{dependent_pkg_list.join(" -> ")}]" - else - @log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK" - end - return true - end - - public - # install local package (ignore dependent packages) - def install_local_pkg(pkg_path, force) - - file_name = File.basename(pkg_path) - pkg_name = file_name.split('_')[0] - - if not File.exist? pkg_path then - @log.error "\"#{pkg_path}\" file does not exist" - return false - end - filename = File.basename(pkg_path) - ext = File.extname(filename) - if not ext.eql? ".zip" then - @log.error "\"#{file_name}\" is not zip file. binary package file should have .zip ext" - return false - end - pkg_name = filename.split("_")[0] - type = "binary" - manifest_file = "pkginfo.manifest" - pkg_config_path = File.join(@location, PACKAGE_INFO_DIR, pkg_name) - - uniq_name = Utils.create_uniq_name - path = Utils::HOME + "/tmp/#{uniq_name}" - FileUtils.mkdir_p "#{path}" - if not FileInstaller.extract_specified_file(pkg_path, manifest_file, path) then - @log.error "pkginfo.manifest file does not exist in #{pkg_path}" - return false - end - manifest_path = File.join(path, manifest_file) - pkg_hash = Parser.read_pkg_list(manifest_path) - new_pkg_ver = pkg_hash[pkg_name].version - FileUtils.rm_f(manifest_path) - FileUtils.remove_dir(path, true) - - compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) - if not force then - case compare_result - when -1 then - @log.warn "\"#{pkg_name}\" package version is bigger then remote package version.." - return true - when 0 then - @log.warn "\"#{pkg_name}\" package version is same with remote package version.." - return true - when 1, 2 then - end - end - - if check_installed_pkg(pkg_name) then - uninstall(pkg_name, false) - end - - # install package - ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location) - - add_local_pkg_info(pkg_name) - write_pkg_hash_to_file(nil) - - @log.info "Installed \"#{pkg_path} [#{new_pkg_ver}]\" file.. OK" - return true - end - - public - # upgrade package - def upgrade(os, trace) - - if trace.nil? then trace = true end - list = check_upgrade(os) - - if list.empty? or list.nil? then - @log.info "There is no packages for upgrading.." - return false - end - - list.each do |p| - if check_installed_pkg(p) then - if not uninstall(p, trace) then - @log.error "Failed to uninstall \"#{p}\" package.." - return false - end - end - - if not install(p, os, trace, false) then - @log.error "Failed to install \"#{p}\" package.." - return false - end - end - - @log.info "Upgraded packages from #{@server_addr}.. OK" - return true - end - - public - # check package which will be upgraded - def check_upgrade(os) - - update_pkgs = [] - installed_pkg_hash_key = get_installed_pkg_list_file_path() - installed_pkg_hash = installed_pkg_hash_loc[installed_pkg_hash_key] - remote_pkg_hash = pkg_hash_os[os] - - if remote_pkg_hash.nil? then - @log.error "There is no remote package list for #{os}. please pkg-cli update" - return nil - end - - if installed_pkg_hash.nil? then - @log.warn "There is no any installed package in \"#{@location}\"" - return remote_pkg_hash.keys - end - - arr_keys = installed_pkg_hash.keys - arr_keys.each do |k| - installed_ver = get_attr_from_installed_pkg(k, "version") - if not check_remote_pkg(k, os) then next end - remote_ver = get_attr_from_pkg(k, os, "version") - compare_result = compare_version_with_installed_pkg(k, remote_ver) - case compare_result - when -1 then next - when 0 then next - when 1 then - @log.output "\"#{k}\" package : #{installed_ver} -> #{remote_ver}" - update_pkgs.push(k) - end - end - - @log.info "Checked packages for upgrading.. OK" - return update_pkgs - end - - public - def get_default_server_addr() - filepath = "#{CONFIG_PATH}/config" - server_addr = nil - - if not File.exist? filepath then create_default_config(nil) end - if not File.exist? filepath then - @log.error "There is no default server address in #{filepath}" - return nil - end - - File.open filepath, "r" do |f| - f.each_line do |l| - if l.strip.start_with? "DEFAULT_SERVER_ADDR :" then - server_addr = l.split("DEFAULT_SERVER_ADDR :")[1].strip - break - else next end - end - end - - if server_addr.nil? then create_default_config(DEFAULT_SERVER_ADDR) end - return server_addr - end - - public - # get default path for installing - def get_default_inst_dir() - return Dir.pwd - end - - private - # create default config file (Utils::HOME/.build_tools/client/config) - def create_default_config(server_addr) - filepath = "#{CONFIG_PATH}/config" - if server_addr.nil? then server_addr = DEFAULT_SERVER_ADDR end - - if File.exist? filepath then - FileUtils.rm_f(filepath) - end - - if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end - - File.open(filepath, "a+") do |file| - file.puts "DEFAULT_SERVER_ADDR : #{server_addr}" - end - end - - public - # uninstall package - # trace : if true, uninstall all dependent packages - def uninstall(pkg_name, trace) - - type = "binary" - pkg_list = [] - pkg_hash = nil - - if not check_installed_pkg(pkg_name) then - @log.error "\"#{pkg_name}\" package is not installed." - return false - end - - pkg_ver = get_attr_from_installed_pkg(pkg_name, "version") - - if trace then - pkg_list = get_all_reverse_install_dependent_packages(pkg_name, true) - if pkg_list.nil? then - @log.error "Failed to get \"#{pkg_name}\" package dependency information." - return false - end - else - pkg_list.push(pkg_name) - end - - pkg_list.each do |p| - if not check_installed_pkg(p) then next end - if not FileInstaller.uninstall(p, type, @location) then - @log.error "Failed uninstall \"#{pkg_name}\" package" - return false - end - pkg_hash = remove_pkg_info(p) - end - - if trace then - @log.info "Uninstalled \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK" - @log.info " [#{pkg_list.join(" -> ")}]" - else - @log.info "Uninstalled only \"#{pkg_name} [#{pkg_ver}]\" package.. OK" - end - - write_pkg_hash_to_file(nil) - return true - end - - public - # clean - def clean(force) - if not force then - puts "Do you really want to remove \"#{@location}\" path? [yes]" - input = $stdin.gets.strip - if input.upcase.eql? "YES" then - @log.info "Removed \"#{@location}\"" - else - @log.info "Canceled" - return - end - end - FileUtils.rm_rf(@location) - FileUtils.mkdir_p(@location) - @pkg_hash_os.clear - @installed_pkg_hash_loc.clear - @archive_pkg_list.clear - @log.info "Cleaned \"#{@location}\" path.. OK" - end - - public + # install all install dependency packages + def install(pkg_name, os, trace, force) + + ret = install_internal( pkg_name, os, trace, force ) + return ret + end + + + private + def install_internal(pkg_name, os, trace, force) + + if trace.nil? then trace = true end + if force.nil? then force = false end + + # check meta package + is_meta_pkg = check_meta_pkg(pkg_name, os) + if is_meta_pkg then trace = true end + + # compare package version with installed package's + pkg_ver = get_attr_from_pkg(pkg_name, os, "version") + if pkg_ver.nil? or pkg_ver.empty? then + @log.error "#{pkg_name} package does not exist in remote package list" + return false + end + + + compare_result = compare_version_with_installed_pkg(pkg_name, pkg_ver) + if not force then + case compare_result + when -1 then + @log.warn "Checked \"#{pkg_name}\" package version : it is bigger then remote package version" + return true + when 0 then + @log.warn "Checked \"#{pkg_name}\" package version : it is same with remote package version" + return true + when 1, 2 then + end + end + + # if enable trace, create all dependent package list + if trace then + dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, force) + if dependent_pkg_list.nil? then + @log.error "Failed to get dependency for \"#{pkg_name}\" package" + return false + end + else + dependent_pkg_list = [pkg_name] + end + + # TODO: need to compare dependent package version + # install packages including dependent packages + dependent_pkg_list.each do |pkg| + if not install_pkg(pkg, os, force) then + @log.error "#{pkg} does not exist" + return false + end + add_pkg_info(pkg, os) + end + + # write installed package information to file + write_pkg_hash_to_file(nil) + + if trace then + @log.info "Installed \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK" + @log.info " [#{dependent_pkg_list.join(" -> ")}]" + else + @log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK" + end + + return true + end + + + public + # install local package (ignore dependent packages) + def install_local_pkg(pkg_path, trace, force, repos_paths = nil) + + ret = install_local_pkg_internal(pkg_path, trace, force, repos_paths) + return ret + end + + + private + def install_local_pkg_internal(pkg_path, trace, force, repos_paths) + + file_name = File.basename(pkg_path) + pkg_name = file_name.split('_')[0] + + if not File.exist? pkg_path then + @log.error "\"#{pkg_path}\" file does not exist" + return false + end + filename = File.basename(pkg_path) + ext = File.extname(filename) + if not ext.eql? ".zip" then + @log.error "\"#{file_name}\" is not zip file. binary package file should have .zip ext" + return false + end + pkg_name = filename.split("_")[0] + manifest_file = "pkginfo.manifest" + + uniq_name = Utils.create_uniq_name + path = Utils::HOME + "/tmp/#{uniq_name}" + if not File.exist? path then FileUtils.mkdir_p "#{path}" end + begin + if not FileInstaller.extract_a_file(pkg_path, manifest_file, path, @log) then + @log.error "pkginfo.manifest file does not exist in #{pkg_path}" + return false + end + manifest_path = File.join(path, manifest_file) + pkg = Parser.read_single_pkginfo_from manifest_path + new_pkg_ver = pkg.version + FileUtils.remove_dir(path, true) + rescue Interrupt + @log.error "Client: Interrupted.." + FileUtils.remove_dir(path, true) + @log.info "Removed #{path}" + raise Interrupt + rescue RuntimeError => e + @log.error( e.message, Log::LV_USER) + FileUtils.remove_dir(path, true) + @log.info "Removed #{path}" + return false + end + + compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) + if not force then + case compare_result + when -1 then + @log.warn "Installed \"#{pkg_name}\" package version is bigger.." + return true + when 0 then + @log.warn "Checked \"#{pkg_name}\" package version : it is same with installed package version" + return true + when 1, 2 then + end + end + + if check_installed_pkg(pkg_name) then + uninstall(pkg_name, false) + end + + if trace then + install_dep_pkgs = pkg.install_dep_list + new_pkg_os = pkg.os + install_dep_pkgs.each do |p| + # check local path first + if not repos_paths.nil? then + # search + binpkgs = [] + repos_paths.each do |repos_path| + binpkgs += Dir.glob("#{repos_path}/#{p.package_name}_*_#{new_pkg_os}.zip") + end + if not binpkgs.empty? then + if not install_local_pkg_internal(binpkgs[0], true, false, repos_paths) then + @log.warn "#{p} package is not installed" + end + else + if not install_internal(p.package_name, new_pkg_os, true, false) then + @log.warn "#{p} package is not installed" + end + end + else + if not install_internal(p.package_name, new_pkg_os, true, false) then + @log.warn "#{p} package is not installed" + end + end + end + end + + # install package + ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location, @log) + + if not ret then + @log.error "Install failed \"#{pkg_path} [#{new_pkg_ver}]\" file.. " + return false + end + + add_local_pkg_info(pkg_name) + write_pkg_hash_to_file(nil) + + @log.info "Installed \"#{pkg_path} [#{new_pkg_ver}]\" file.. OK" + return true + end + + + public + # upgrade package + def upgrade(os, trace) + + if trace.nil? then trace = true end + list = check_upgrade(os) + + if list.empty? or list.nil? then + @log.info "There is no packages for upgrading.." + return false + end + + list.each do |p| + if check_installed_pkg(p) then + if not uninstall(p, trace) then + @log.error "Failed to uninstall \"#{p}\" package.." + return false + end + end + + if not install_internal(p, os, trace, false) then + @log.error "Failed to install \"#{p}\" package.." + return false + end + end + + @log.info "Upgraded packages from #{@server_addr}.. OK" + return true + end + + public + # check package which will be upgraded + def check_upgrade(os) + + update_pkgs = [] + installed_pkg_hash_key = get_installed_pkg_list_file_path() + installed_pkg_hash = installed_pkg_hash_loc[installed_pkg_hash_key] + remote_pkg_hash = pkg_hash_os[os] + + if remote_pkg_hash.nil? then + @log.error "There is no remote package list for #{os}. please pkg-cli update" + return nil + end + + if installed_pkg_hash.nil? then + @log.warn "There is no any installed package in \"#{@location}\"" + return remote_pkg_hash.keys + end + + arr_keys = installed_pkg_hash.keys + arr_keys.each do |k| + installed_ver = get_attr_from_installed_pkg(k, "version") + if not check_remote_pkg(k, os) then next end + remote_ver = get_attr_from_pkg(k, os, "version") + compare_result = compare_version_with_installed_pkg(k, remote_ver) + case compare_result + when -1 then next + when 0 then next + when 1 then + @log.output "\"#{k}\" package : #{installed_ver} -> #{remote_ver}" + update_pkgs.push(k) + end + end + + @log.info "Checked packages for upgrading.. OK" + return update_pkgs + end + + public + def get_default_server_addr() + filepath = "#{CONFIG_PATH}/config" + server_addr = nil + + if not File.exist? filepath then create_default_config(nil) end + if not File.exist? filepath then + @log.error "There is no default server address in #{filepath}" + return nil + end + + File.open filepath, "r" do |f| + f.each_line do |l| + if l.strip.start_with? "DEFAULT_SERVER_ADDR :" then + server_addr = l.split("DEFAULT_SERVER_ADDR :")[1].strip + break + else next end + end + end + + if server_addr.nil? then create_default_config(DEFAULT_SERVER_ADDR) end + return server_addr + end + + public + # get default path for installing + def get_default_inst_dir() + return Dir.pwd + end + + private + # create default config file (Utils::HOME/.build_tools/client/config) + def create_default_config(server_addr) + filepath = "#{CONFIG_PATH}/config" + if server_addr.nil? then server_addr = DEFAULT_SERVER_ADDR end + + if File.exist? filepath then + FileUtils.rm_f(filepath) + end + + if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end + + File.open(filepath, "a+") do |file| + file.puts "DEFAULT_SERVER_ADDR : #{server_addr}" + end + end + + public + # uninstall package + # trace : if true, uninstall all dependent packages + def uninstall(pkg_name, trace) + + type = "binary" + pkg_list = [] + pkg_hash = nil + + if not check_installed_pkg(pkg_name) then + @log.error "\"#{pkg_name}\" package is not installed." + return false + end + + pkg_ver = get_attr_from_installed_pkg(pkg_name, "version") + + if trace then + pkg_list = get_all_reverse_install_dependent_packages(pkg_name, true) + if pkg_list.nil? then + @log.error "Failed to get \"#{pkg_name}\" package dependency information." + return false + end + else + pkg_list.push(pkg_name) + end + + pkg_list.each do |p| + if not check_installed_pkg(p) then next end + if not FileInstaller.uninstall(p, type, @location, @log) then + @log.error "Failed uninstall \"#{pkg_name}\" package" + return false + end + pkg_hash = remove_pkg_info(p) + end + + if trace then + @log.info "Uninstalled \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK" + @log.info " [#{pkg_list.join(" -> ")}]" + else + @log.info "Uninstalled only \"#{pkg_name} [#{pkg_ver}]\" package.. OK" + end + + write_pkg_hash_to_file(nil) + return true + end + + public + # clean + def clean(force) + if not force then + puts "Do you really want to remove \"#{@location}\" path? [yes]" + input = $stdin.gets.strip + if input.upcase.eql? "YES" then + @log.info "Removed \"#{@location}\"" + else + @log.info "Canceled" + return + end + end + if File.exist? @location then FileUtils.rm_rf(@location) end + FileUtils.mkdir_p(@location) + #@pkg_hash_os.clear + @installed_pkg_hash_loc.clear + #@archive_pkg_list.clear + @log.info "Cleaned \"#{@location}\" path.. OK" + end + + public # get reverse build dependent packages (just 1 depth) - def get_reverse_build_dependent_packages(pkg_name, os) - - result = [] - pkg_hash = @pkg_hash_os[os] - pkg_list = pkg_hash.values - pkg_list.each do |pkg| - pkg.build_dep_list.each do |dep| - if dep.package_name.eql? pkg_name and - not dep.target_os_list.nil? and + def get_reverse_build_dependent_packages(pkg_name, os) + + result = [] + pkg_hash = @pkg_hash_os[os] + if pkg_hash.nil? then return [] end + pkg_list = pkg_hash.values + pkg_list.each do |pkg| + pkg.build_dep_list.each do |dep| + if dep.package_name.eql? pkg_name and + not dep.target_os_list.nil? and dep.target_os_list.include? os then - result.push(pkg.package_name) - end - end - end + result.push(pkg) + end + end + end - return result - end + return result + end - public + public # get reverse source dependent packages (just 1 depth) - def get_reverse_source_dependent_packages(pkg_name, os) - - result = [] - pkg_hash = @pkg_hash_os[os] - pkg_list = pkg_hash.values - pkg_list.each do |pkg| - pkg.source_dep_list.each do |p| - if p.package_name.eql? pkg_name then - result.push(pkg.package_name) - end - end - end - - return result - end - - public + def get_reverse_source_dependent_packages(pkg_name) + + result = [] + @support_os_list.each do |os| + pkg_hash = @pkg_hash_os[os] + pkg_list = pkg_hash.values + pkg_list.each do |pkg| + pkg.source_dep_list.each do |p| + if p.package_name.eql? pkg_name then + result.push(pkg) + end + end + end + end + + return result + end + + public # get reverse install dependent packages (jush 1 depth) - def get_reverse_install_dependent_packages(pkg_name, os) - - result = [] - pkg_hash = @pkg_hash_os[os] - pkg_list = pkg_hash.values - pkg_list.each do |pkg| - pkg.install_dep_list.each do |p| - if p.package_name.eql? pkg_name then - result.push(pkg.package_name) - end - end - end - - return result - end - - public + def get_reverse_install_dependent_packages(pkg_name, os) + + result = [] + pkg_hash = @pkg_hash_os[os] + pkg_list = pkg_hash.values + pkg_list.each do |pkg| + pkg.install_dep_list.each do |p| + if p.package_name.eql? pkg_name then + result.push(pkg.package_name) + end + end + end + + return result + end + + public # get all build dependent packages (considered build priority, and reverse) - def get_build_dependent_packages(pkg_name, os, reverse) - - if not check_remote_pkg(pkg_name, os) then return nil end - if reverse.nil? then reverse = true end - - @all_dep_list.clear - begin - get_build_dependency_arr(pkg_name, os, 0) - # in case of cross build dependency - rescue SystemStackError - @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." - return nil - end - - max = 0 - @all_dep_list.each do |p| - if p[0].to_i > max then - max = p[0].to_i - else next end - end - - result = [] - i = 0 - while i <= max - @all_dep_list.each do |p| - if p[0].to_i.eql? i then - d = p[1] - remote_os = get_attr_from_pkg(d.package_name, os, "os") - remote_ver = get_attr_from_pkg(d.package_name, os, "version") - if not d.target_os_list.include? remote_os then - @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.target_os_list.to_s}, but \"#{d.package_name}\" (#{remote_os}) package is in server" - return nil - end - if not d.match? remote_ver then - @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server" - return nil - else result.push(d.package_name) end - end - end - i = i + 1 - end - - @log.info "Get build dependent packages for #{pkg_name} package.. OK" - if reverse then return result.reverse.uniq.push(pkg_name) - else return result.uniq.insert(0, pkg_name) end - end - - public + def get_build_dependent_packages(pkg_name, os, reverse) + + if not check_remote_pkg(pkg_name, os) then return nil end + if reverse.nil? then reverse = true end + + @all_dep_list.clear + begin + get_build_dependency_arr(pkg_name, os, 0) + # in case of cross build dependency + rescue SystemStackError + @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." + return nil + end + + max = 0 + @all_dep_list.each do |p| + if p[0].to_i > max then + max = p[0].to_i + else next end + end + + result = [] + i = 0 + while i <= max + @all_dep_list.each do |p| + if p[0].to_i.eql? i then + d = p[1] + remote_os = get_attr_from_pkg(d.package_name, os, "os") + remote_ver = get_attr_from_pkg(d.package_name, os, "version") + if not d.target_os_list.include? remote_os then + @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.target_os_list.to_s}, but \"#{d.package_name}\" (#{remote_os}) package is in server" + return nil + end + if not d.match? remote_ver then + @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server" + return nil + else result.push(d.package_name) end + end + end + i = i + 1 + end + + @log.info "Get build dependent packages for #{pkg_name} package.. OK" + if reverse then return result.reverse.uniq.push(pkg_name) + else return result.uniq.insert(0, pkg_name) end + end + + public # get all install dependent packages (considered install priority, reverse, and force) - # reverse : return reverse result - # force : install package force - def get_install_dependent_packages(pkg_name, os, reverse, force) - - if not check_remote_pkg(pkg_name, os) then return nil end - if reverse.nil? then reverse = true end - - @all_dep_list.clear - begin - get_install_dependency_arr(pkg_name, os, force, 0) - # in case of cross build dependency - rescue SystemStackError - @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." - return nil - end - - max = 0 - @all_dep_list.each do |p| - if p[0].to_i > max then - max = p[0].to_i - else next end - end - - result = [] - i = 0 - while i <= max - @all_dep_list.each do |p| - if p[0].to_i.eql? i then - d = p[1] - remote_ver = get_attr_from_pkg(d.package_name, os, "version") - if not d.match? remote_ver then - @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server" - return nil - else result.push(d.package_name) end - end - end - i = i + 1 - end - - @log.info "Get install dependent packages for #{pkg_name} package.. OK" - if reverse then return result.reverse.uniq.push(pkg_name) - else return result.uniq.insert(0, pkg_name) end - end - - public - # get all reverse install dependent packages (considered reverse install priority for tracing uninstall) - def get_all_reverse_install_dependent_packages(pkg_name, reverse) - - if not check_installed_pkg(pkg_name) then return nil end - if reverse.nil? then reverse = true end - - begin - res = get_all_reverse_install_dependency_arr(pkg_name, 0) - rescue SystemStackError - @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." - return nil - end - res2 = res.split("::") - result = [] - res2.each do |r| - result.push(r.split(':')[1]) - end - - @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK" - if reverse then return result.reverse.uniq - else return result end - end - - public - # get all reverse remote dependent packages (considered reverse install priority for tracing uninstall) - def get_all_reverse_install_dependent_packages_remote(pkg_name, os, reverse) - #if not check_remote_pkg(pkg_name, os) then return nil end - if reverse.nil? then reverse = true end - - begin - res = get_all_reverse_install_dependency_arr_remote(pkg_name, os, 0) - rescue SystemStackError - @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." - return nil - end - res2 = res.split("::") - result = [] - res2.each do |r| - result.push(r.split(':')[1]) - end - - @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK" - if reverse then return result.reverse - else return result end - end - - public - # check package whether to exist in remote server - def check_remote_pkg(pkg_name, os) - - pkg_hash = @pkg_hash_os[os] - if pkg_hash.nil? then return false end - pkg = pkg_hash[pkg_name] - if pkg.nil? then - @log.warn "There is no \"#{pkg_name}\" remote package information in list" - return false - end - - return true - end - - public - # check package whether to exist in installed packages - def check_installed_pkg(pkg_name) - - installed_pkg_hash_key = get_installed_pkg_list_file_path() - pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] - if pkg_hash.nil? then return false end - pkg = pkg_hash[pkg_name] - - if pkg.nil? then return false end - return true - end - - public - # get attribute from installed package - def get_attr_from_installed_pkg(pkg_name, attr) - - if not check_installed_pkg(pkg_name) then return nil end - pkg = get_installed_pkg_from_list(pkg_name) - - if pkg.nil? then return nil end - - case attr - when "version" then return pkg.version - when "source" then return pkg.source - when "src_path" then return pkg.src_path - when "os" then return pkg.os - when "build_dep_list" then return pkg.build_dep_list - when "install_dep_list" then return pkg.install_dep_list - when "attribute" then return pkg.attribute - end - end - - public - # get attribute from remote package - def get_attr_from_pkg(pkg_name, os, attr) - - if not check_remote_pkg(pkg_name, os) then return nil end - pkg = get_pkg_from_list(pkg_name, os) - - if pkg.nil? then return nil end - - case attr - when "path" then return pkg.path - when "source" then return pkg.source - when "version" then return pkg.version - when "src_path" then return pkg.src_path - when "os" then return pkg.os - when "build_dep_list" then return pkg.build_dep_list - when "install_dep_list" then return pkg.install_dep_list - when "attribute" then return pkg.attribute - end - end - - public - # show a package information - def show_pkg_info(pkg_name, os) - if not check_remote_pkg(pkg_name, os) then - @log.error "\"#{pkg_name}\" package does not exist" - return "" - end - - pkg = get_pkg_from_list(pkg_name, os) - return pkg.to_s - end - - public - # show all packages information - def show_pkg_list(os) - pkg_hash = @pkg_hash_os[os] - if pkg_hash.nil? then - @log.error "\"#{os}\" package list does not exist" - return "" - end - - pkg_all_list = [] - pkg_list = pkg_hash.values - pkg_list.each do |p| - pkg_all_list.push([p.package_name, p.version, p.description]) - end - return pkg_all_list.sort - end - - public - # show installed package information - def show_installed_pkg_info(pkg_name) - - if not check_installed_pkg(pkg_name) then - @log.error "\"#{pkg_name}\" package does not exist" - return "" - end - - pkg = get_installed_pkg_from_list(pkg_name) - return pkg.to_s - end - - public - # show all installed packages information - def show_installed_pkg_list() - - file_path = get_installed_pkg_list_file_path() - pkg_hash = @installed_pkg_hash_loc[file_path] - if pkg_hash.nil? then - @log.error "Installed package list does not exist" - return - end - pkg_all_list = [] - pkg_list = pkg_hash.values - pkg_list.each do |p| - pkg_all_list.push([p.package_name, p.version, p.description]) - end - return pkg_all_list.sort - end - - private - def get_build_dependency_arr(pkg_name, os, n) - pkg_hash = @pkg_hash_os[os] - pkg = pkg_hash[pkg_name] - - if pkg.nil? then - @log.error "\"#{pkg_name}\" package does not exist in server. please check it" - return - end - - # if package is already installed, skip tracing dependency - if check_installed_pkg(pkg_name) then - # compare version with installed package version - new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version") - compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) - if compare_result == -1 or compare_result == 0 then return end - end - - pkg.build_dep_list.each do |l| - @all_dep_list.push([n, l]) - get_build_dependency_arr(l.package_name, os, n+1) - end - - return - end - - private - def get_install_dependency_arr(pkg_name, os, force, n) - - pkg_hash = @pkg_hash_os[os] - pkg = pkg_hash[pkg_name] - - if pkg.nil? then - @log.error "\"#{pkg_name}\" package does not exist in server. please check it" - return - end - - # if package is already installed, skip tracing dependency - if check_installed_pkg(pkg_name) then - # compare version with installed package version - new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version") - compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) - if not force then - if compare_result == -1 or compare_result == 0 then return end - end - end - - pkg.install_dep_list.each do |l| - @all_dep_list.push([n, l]) - get_install_dependency_arr(l.package_name, os, force, n+1) - end - - return - end - - private - def get_all_reverse_install_dependency_arr(pkg_name, n) - - s = "#{n}:#{pkg_name}" - installed_pkg_hash_key = get_installed_pkg_list_file_path() - pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] - pkg_list = pkg_hash.values - pkg_list.each do |pkg| - pkg.install_dep_list.each do |l| - if l.package_name.eql? pkg_name then - s = s + "::" + get_all_reverse_install_dependency_arr(pkg.package_name, n+1) - end - end - end - - return s - end - - private - def get_all_reverse_install_dependency_arr_remote(pkg_name, os, n) - - s = "#{n}:#{pkg_name}" - pkg_hash = @pkg_hash_os[os] - pkg_list = pkg_hash.values - pkg_list.each do |pkg| - pkg.install_dep_list.each do |l| - if l.package_name.eql? pkg_name then - s = s + "::" + get_all_reverse_install_dependency_arr_remote(pkg.package_name, os, n+1) - end - end - end - - return s - end - - private - def get_pkg_from_list(pkg_name, os) - - pkg_hash = @pkg_hash_os[os] - if pkg_hash.nil? then return nil end - pkg = pkg_hash[pkg_name] - - return pkg - end - - private - def get_installed_pkg_from_list(pkg_name) - - installed_pkg_hash_key = get_installed_pkg_list_file_path() - pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] - pkg = pkg_hash[pkg_name] - if pkg.nil? then return nil end - - return pkg - end - - private - def install_pkg(pkg_name, os, force) - - new_pkg_ver = "" - - # install remote server package file - if not check_remote_pkg(pkg_name, os) then - @log.error "\"#{pkg_name}\" package does not exist in remote server" - return false - end - path = get_attr_from_pkg(pkg_name, os, "path") - # type should be binary. type = "binary" - # below code should be changed - type = path.split('/')[-2] - new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version") - - # compare version with installed package versiona - compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) - if not force then - case compare_result - when -1 then - @log.warn "\"#{pkg_name}\" package version is bigger then remote package version" - return true - when 0 then - @log.warn "\"#{pkg_name}\" package version is same with remote package version" - return true - end - end - - if check_installed_pkg(pkg_name) then - uninstall(pkg_name, false) - end - - # download file - # change download location temporary (back to the origin path after downloading) - loc_back = @location - uniq_name = Utils.create_uniq_name - tmppath = Utils::HOME + "/tmp/#{uniq_name}" - FileUtils.mkdir_p "#{tmppath}" - @location = tmppath - file_local_path = download(pkg_name, os, false)[0] - @location = loc_back - if file_local_path.nil? then return false end - - # install package - ret = FileInstaller.install(pkg_name, file_local_path, type, @location) - FileUtils.rm_f(file_local_path) - FileUtils.remove_dir(tmppath, true) - return ret - end - - private - def compare_version_with_installed_pkg(pkg_name, new_pkg_ver) - - if check_installed_pkg_list_file() then - create_installed_pkg_hash() - if check_installed_pkg(pkg_name) then - installed_pkg_ver = get_attr_from_installed_pkg(pkg_name, "version") - compare_result = Utils.compare_version(installed_pkg_ver, new_pkg_ver) - return compare_result - end - end - - return 2 - end - - private - def remove_pkg_info(pkg_name) - - pkg_hash = {} - installed_pkg_hash_key = get_installed_pkg_list_file_path() - if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then - pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] - if pkg_hash.include? pkg_name then - pkg_hash.delete(pkg_name) - end - @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash - else return nil end - - @log.info "Removed information for \"#{pkg_name}\" package.. OK" - return pkg_hash - end - - private - def add_pkg_info(pkg_name, os) - - pkg_hash = {} - installed_pkg_hash_key = get_installed_pkg_list_file_path() - if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then - pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] - pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) - else pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) end - @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash - - @log.info "Added information for \"#{pkg_name}\" package.. OK" - return pkg_hash - end - - private - # add package manifest info - def add_local_pkg_info(pkg_name) - - config_path = File.join(@location, PACKAGE_INFO_DIR, "#{pkg_name}") - pkg = read_pkginfo_file(pkg_name, config_path) - - if pkg.nil? then - @log.error "Failed to read pkginfo.manifest file" - return nil - end - - pkg_hash = {} - installed_pkg_hash_key = get_installed_pkg_list_file_path() - if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then - pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] - pkg_hash[pkg_name] = pkg - else pkg_hash[pkg_name] = pkg end - @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash - - @log.info "Added information for \"#{pkg_name}\" package.. OK" - return pkg_hash - end - - private - # read package manifet info - def read_pkginfo_file(pkg_name, path) - - file_path = File.join(path, "pkginfo.manifest") - pkg_hash = Parser.read_pkg_list(file_path) - - if pkg_hash.nil? then - @log.error "Failed to read manifest file : #{file_path}" - return nil - end - - @log.info "Added information for \"#{pkg_name}\" package.. OK" - return pkg_hash[pkg_name] - end - - private - # from_server : if true, update from server - def create_remote_pkg_hash(from_server) - - for os in SUPPORTED_OS - filename = PKG_LIST_FILE_PREFIX + os - file_url = @server_addr + "/" + filename - local_file_path = File.join(CONFIG_PATH, filename) - if from_server then - if not FileDownLoader.download(file_url, CONFIG_PATH) then - return false - end - end - local_file_path = File.join(CONFIG_PATH, filename) - if File.exist? local_file_path then - pkg_hash = Parser.read_pkg_list(local_file_path) - @pkg_hash_os[os] = pkg_hash - end - end - - filename = "archive_pkg_list" - file_url = @server_addr + "/" + filename - if from_server then - if not FileDownLoader.download(file_url, CONFIG_PATH) then - @log.warn "Server does not have \"#{filename}\" file. This error can be ignored." - end - end - local_file_path = File.join(CONFIG_PATH, filename) - if File.exist? local_file_path then - File.open(local_file_path, "r") do |f| - f.each_line do |l| - @archive_pkg_list.push(l.strip) - end - end - end - - return true - end - - private - # create installed package hash - def create_installed_pkg_hash() - - config_path = File.join(@location, PACKAGE_INFO_DIR) - if not File.directory? config_path then return end - - installed_pkg_hash_key = get_installed_pkg_list_file_path() - if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then return - else - file_path = installed_pkg_hash_key - if not File.exist? file_path then - #raise RuntimeError, "#{file_path} file does not exist" - return - end - pkg_hash = Parser.read_pkg_list(file_path) - @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash - end - end - - private - # check to exist installed package list file - def check_installed_pkg_list_file() - - if @location.nil? then raise RuntimeError, "#{@location} path does not exist" end - file_path = get_installed_pkg_list_file_path() - if File.exist? file_path then return true - else return false end - end - - private - # get installed package list file path - def get_installed_pkg_list_file_path() - - file_full_path = File.join(@location, PACKAGE_INFO_DIR, INSTALLED_PKG_LIST_FILE) - return file_full_path - end - - private - # write package hash to file - def write_pkg_hash_to_file(pkg_hash) - - file_path = get_installed_pkg_list_file_path() - if pkg_hash.nil? then - pkg_hash = @installed_pkg_hash_loc[file_path] - end - if not pkg_hash.nil? then - config_path = File.join(@location, PACKAGE_INFO_DIR) - FileUtils.mkdir_p "#{config_path}" - if File.exist? file_path then File.delete(file_path) end - File.open(file_path, "a+") do |file| - file.puts "ORIGIN : #{@server_addr}" - file.puts "\n" - pkg_list = pkg_hash.values - pkg_list.each do |pkg| - pkg.print_to_file(file) - file.puts "\n" - end - end - end - @log.info "Write package informations to \"#{file_path}\".. OK" - end - - private - def check_meta_pkg(pkg_name, os) - if not check_remote_pkg(pkg_name, os) then return false end - - attr = get_attr_from_pkg(pkg_name, os, "attribute") - if attr.nil? or attr.empty? then return false end - if attr[0].strip.upcase.eql? "META" then return true - else return false end - end + # reverse : return reverse result + # force : install package force + def get_install_dependent_packages(pkg_name, os, reverse, force) + + if not check_remote_pkg(pkg_name, os) then return nil end + if reverse.nil? then reverse = true end + + @all_dep_list.clear + begin + get_install_dependency_arr(pkg_name, os, force, 0) + # in case of cross build dependency + rescue SystemStackError + @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." + return nil + end + + max = 0 + @all_dep_list.each do |p| + if p[0].to_i > max then + max = p[0].to_i + else next end + end + + result = [] + i = 0 + while i <= max + @all_dep_list.each do |p| + if p[0].to_i.eql? i then + d = p[1] + remote_ver = get_attr_from_pkg(d.package_name, os, "version") + if not d.match? remote_ver then + @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server" + return nil + else result.push(d.package_name) end + end + end + i = i + 1 + end + + @log.info "Get install dependent packages for \"#{pkg_name}\" package.. OK" + if reverse then return result.reverse.uniq.push(pkg_name) + else return result.uniq.insert(0, pkg_name) end + end + + public + # get all reverse install dependent packages (considered reverse install priority for tracing uninstall) + def get_all_reverse_install_dependent_packages(pkg_name, reverse) + + if not check_installed_pkg(pkg_name) then return nil end + if reverse.nil? then reverse = true end + + begin + res = get_all_reverse_install_dependency_arr(pkg_name, 0) + rescue SystemStackError + @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." + return nil + end + res2 = res.split("::") + result = [] + res2.each do |r| + result.push(r.split(':')[1]) + end + + @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK" + if reverse then return result.reverse.uniq + else return result end + end + + public + # get all reverse remote dependent packages (considered reverse install priority for tracing uninstall) + def get_all_reverse_install_dependent_packages_remote(pkg_name, os, reverse) + #if not check_remote_pkg(pkg_name, os) then return nil end + if reverse.nil? then reverse = true end + + begin + res = get_all_reverse_install_dependency_arr_remote(pkg_name, os, 0) + rescue SystemStackError + @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency." + return nil + end + res2 = res.split("::") + result = [] + res2.each do |r| + result.push(r.split(':')[1]) + end + + @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK" + if reverse then return result.reverse + else return result end + end + + public + # check package whether to exist in remote server + def check_remote_pkg(pkg_name, os) + + pkg_hash = @pkg_hash_os[os] + if pkg_hash.nil? then return false end + pkg = pkg_hash[pkg_name] + if pkg.nil? then + #@log.warn "There is no \"#{pkg_name}\" remote package information in list" + return false + end + + return true + end + + public + # check package whether to exist in installed packages + def check_installed_pkg(pkg_name) + + installed_pkg_hash_key = get_installed_pkg_list_file_path() + pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] + if pkg_hash.nil? then return false end + pkg = pkg_hash[pkg_name] + + if pkg.nil? then return false end + return true + end + + public + # get attribute from installed package + def get_attr_from_installed_pkg(pkg_name, attr) + + if not check_installed_pkg(pkg_name) then return nil end + pkg = get_installed_pkg_from_list(pkg_name) + + if pkg.nil? then return nil end + + case attr + when "version" then return pkg.version + when "source" then return pkg.source + when "src_path" then return pkg.src_path + when "os" then return pkg.os + when "build_dep_list" then return pkg.build_dep_list + when "install_dep_list" then return pkg.install_dep_list + when "attribute" then return pkg.attribute + end + end + + public + # get attribute from remote package + def get_attr_from_pkg(pkg_name, os, attr) + + if not check_remote_pkg(pkg_name, os) then return nil end + pkg = get_pkg_from_list(pkg_name, os) + + if pkg.nil? then return nil end + + case attr + when "name" then return pkg.package_name + when "path" then return pkg.path + when "source" then return pkg.source + when "version" then return pkg.version + when "src_path" then return pkg.src_path + when "os" then return pkg.os + when "build_dep_list" then return pkg.build_dep_list + when "install_dep_list" then return pkg.install_dep_list + when "attribute" then return pkg.attribute + when "checksum" then return pkg.checksum + when "size" then return pkg.size + + end + end + + public + # show a package information + def show_pkg_info(pkg_name, os) + if not check_remote_pkg(pkg_name, os) then + @log.error "\"#{pkg_name}\" package does not exist" + return "" + end + + pkg = get_pkg_from_list(pkg_name, os) + return pkg.to_s + end + + public + # show all packages information + def show_pkg_list(os) + pkg_hash = @pkg_hash_os[os] + if pkg_hash.nil? then + @log.error "\"#{os}\" package list does not exist" + return "" + end + + pkg_all_list = [] + pkg_list = pkg_hash.values + pkg_list.each do |p| + pkg_all_list.push([p.package_name, p.version, p.description]) + end + return pkg_all_list.sort + end + + public + # show installed package information + def show_installed_pkg_info(pkg_name) + + if not check_installed_pkg(pkg_name) then + @log.error "\"#{pkg_name}\" package does not exist" + return "" + end + + pkg = get_installed_pkg_from_list(pkg_name) + return pkg.to_s + end + + public + # show all installed packages information + def show_installed_pkg_list() + + file_path = get_installed_pkg_list_file_path() + pkg_hash = @installed_pkg_hash_loc[file_path] + if pkg_hash.nil? then + @log.error "Installed package list does not exist" + return nil + end + pkg_all_list = [] + pkg_list = pkg_hash.values + pkg_list.each do |p| + pkg_all_list.push([p.package_name, p.version, p.description]) + end + return pkg_all_list.sort + end + + private + def get_build_dependency_arr(pkg_name, os, n) + pkg_hash = @pkg_hash_os[os] + pkg = pkg_hash[pkg_name] + + if pkg.nil? then + @log.error "\"#{pkg_name}\" package does not exist in server. please check it" + return + end + + # if package is already installed, skip tracing dependency + if check_installed_pkg(pkg_name) then + # compare version with installed package version + new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version") + compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) + if compare_result == -1 or compare_result == 0 then return end + end + + pkg.build_dep_list.each do |l| + @all_dep_list.push([n, l]) + get_build_dependency_arr(l.package_name, os, n+1) + end + + return + end + + private + def get_install_dependency_arr(pkg_name, os, force, n) + + pkg_hash = @pkg_hash_os[os] + pkg = pkg_hash[pkg_name] + + if pkg.nil? then + @log.error "\"#{pkg_name}\" package does not exist in server. please check it" + return + end + + # if package is already installed, skip tracing dependency + if check_installed_pkg(pkg_name) then + # compare version with installed package version + new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version") + compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) + if not force then + if compare_result == -1 or compare_result == 0 then return end + end + end + + pkg.install_dep_list.each do |l| + @all_dep_list.push([n, l]) + get_install_dependency_arr(l.package_name, os, force, n+1) + end + + return + end + + private + def get_all_reverse_install_dependency_arr(pkg_name, n) + + s = "#{n}:#{pkg_name}" + installed_pkg_hash_key = get_installed_pkg_list_file_path() + pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] + pkg_list = pkg_hash.values + pkg_list.each do |pkg| + pkg.install_dep_list.each do |l| + if l.package_name.eql? pkg_name then + s = s + "::" + get_all_reverse_install_dependency_arr(pkg.package_name, n+1) + end + end + end + + return s + end + + private + def get_all_reverse_install_dependency_arr_remote(pkg_name, os, n) + + s = "#{n}:#{pkg_name}" + pkg_hash = @pkg_hash_os[os] + pkg_list = pkg_hash.values + pkg_list.each do |pkg| + pkg.install_dep_list.each do |l| + if l.package_name.eql? pkg_name then + s = s + "::" + get_all_reverse_install_dependency_arr_remote(pkg.package_name, os, n+1) + end + end + end + + return s + end + + public + def get_pkg_from_list(pkg_name, os) + + pkg_hash = @pkg_hash_os[os] + if pkg_hash.nil? then return nil end + + pkg = pkg_hash[pkg_name] + + return pkg + end + + private + def get_installed_pkg_from_list(pkg_name) + + installed_pkg_hash_key = get_installed_pkg_list_file_path() + pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] + pkg = pkg_hash[pkg_name] + if pkg.nil? then return nil end + + return pkg + end + + private + # install a package to @location after uninstalling and downloading + def install_pkg(pkg_name, os, force) + + new_pkg_ver = "" + + # install remote server package file + if not check_remote_pkg(pkg_name, os) then + @log.error "\"#{pkg_name}\" package does not exist in remote server" + return false + end + path = get_attr_from_pkg(pkg_name, os, "path") + # type should be binary. type = "binary" + # below code should be changed + type = path.split('/')[-2] + new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version") + pkg_checksum = get_attr_from_pkg(pkg_name, os, "checksum") + pkg_size = get_attr_from_pkg(pkg_name, os, "size") + pkg_path = get_attr_from_pkg(pkg_name, os, "path") + filename = pkg_path.split('/')[-1] + + # compare version with installed package versiona + compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver) + if not force then + case compare_result + when -1 then + @log.warn "Checked \"#{pkg_name}\" package version : it is bigger then remote package version" + return true + when 0 then + @log.warn "Checked \"#{pkg_name}\" package version : it is same with remote package version" + return true + end + end + + # if package is already installed, then uninstall it + if check_installed_pkg(pkg_name) then + if not uninstall(pkg_name, false) then + @log.error "Failed to uninstall \"#{pkg_name}\"" + return false + end + end + + # install package + cached_filepath = nil + if Utils.is_linux_like_os( Utils::HOST_OS ) then + cached_filepath = get_cached_filepath(filename, pkg_checksum, pkg_size) + end + if not cached_filepath.nil? then + @log.info "Cached #{pkg_name} package file.. OK" + ret = FileInstaller.install(pkg_name, cached_filepath, type, @location, @log) + else + filepath = download(pkg_name, os, false, @tmp_path) + if filepath.nil? then + return false + end + filepath = move_downloaded_pkg(filepath[0], @download_path) + if filepath.nil? then + return false + end + ret = FileInstaller.install(pkg_name, filepath, type, @location, @log) + remove_downloaded_pkgs(pkg_name, os) + end + return ret + end + + private + def compare_version_with_installed_pkg(pkg_name, new_pkg_ver) + + if check_installed_pkg_list_file() then + read_installed_pkg_list() + if check_installed_pkg(pkg_name) then + installed_pkg_ver = get_attr_from_installed_pkg(pkg_name, "version") + compare_result = Utils.compare_version(installed_pkg_ver, new_pkg_ver) + return compare_result + end + end + + return 2 + end + + private + def remove_pkg_info(pkg_name) + + pkg_hash = {} + installed_pkg_hash_key = get_installed_pkg_list_file_path() + if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then + pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] + if pkg_hash.include? pkg_name then + pkg_hash.delete(pkg_name) + end + @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash + else return nil end + + @log.info "Removed information for \"#{pkg_name}\" package.. OK" + return pkg_hash + end + + private + def add_pkg_info(pkg_name, os) + + pkg_hash = {} + installed_pkg_hash_key = get_installed_pkg_list_file_path() + if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then + pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] + pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) + else pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) end + @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash + + #@log.info "Added information for \"#{pkg_name}\" package.. OK" + return pkg_hash + end + + private + # add package manifest info + def add_local_pkg_info(pkg_name) + + config_path = File.join(@location, PACKAGE_INFO_DIR, "#{pkg_name}") + pkg = read_pkginfo_file(pkg_name, config_path) + + if pkg.nil? then + @log.error "Failed to read pkginfo.manifest file" + return nil + end + + pkg_hash = {} + installed_pkg_hash_key = get_installed_pkg_list_file_path() + if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then + pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key] + pkg_hash[pkg_name] = pkg + else pkg_hash[pkg_name] = pkg end + @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash + + #@log.info "Added information for \"#{pkg_name}\" package.. OK" + return pkg_hash + end + + private + # read package manifet info + def read_pkginfo_file(pkg_name, path) + + file_path = File.join(path, "pkginfo.manifest") + begin + pkg = Parser.read_single_pkginfo_from file_path + rescue => e + @log.error( e.message, Log::LV_USER) + return nil + end + + if pkg.nil? then + @log.error "Failed to read manifest file : #{file_path}" + return nil + end + + @log.info "Read information for \"#{pkg_name}\" package.. OK" + return pkg + end + + # get the lastest snapshot + # from_server : if true, update from server + def get_lastest_snapshot(from_server) + ssinfo_file = "snapshot.info" + file_url = File.join(@server_addr, ssinfo_file) + if from_server then + if not FileDownLoader.download(file_url, @config_dist_path, @log) then + @log.warn "Server does not have \"#{ssinfo_file}\" file. This error can be ignored." + end + else + if File.exist? file_url then FileUtils.cp(file_url, @config_dist_path) + else @log.warn "Server does not have \"#{ssinfo_file}\" file. This error can be ignored." end + end + + file_path = File.join(@config_dist_path, ssinfo_file) + if not File.exist? file_path then return nil end + + contents = File.open(file_path, "r").read + + _list = contents.split("\n\n") + if _list.nil? or _list == "" or _list.empty? then return nil end + list = _list[-1].split("\n") + if list.nil? or list == "" or list.empty? then return nil end + _path = list[-1].split(":") + if _path.nil? or _path == "" or _path.length != 2 then return nil end + path = _path[1].strip + if path == nil or path == "" then return nil end + + return path + end + + def get_pkglist_path() + return File.join(@config_dist_path, @snapshot_path) + end + + # if url includes snapshot infomation, retuen true + def is_snapshot_url(addr = nil) + if addr.nil? then addr = @server_addr end + addr_arr = addr.split('/') + if addr_arr[-2].eql? "snapshots" then + return true + else + return false + end + end + + def split_addr_and_snapshot(addr = nil) + if addr.nil? then addr = @server_addr end + addr_arr = addr.split('/') + if addr_arr[-2].eql? "snapshots" then + return addr_arr[0..-3].join("/"), addr_arr[-2..-1].join("/") + else + return nil + end + end + + def is_snapshot_exist(ss_path = nil) + if ss_path.nil? then ss_path = @snapshot_path + elsif ss_path == "" then return false end + + local_snapshot_path = File.join(@config_dist_path, ss_path) + if File.directory? local_snapshot_path then return true + else return false end + end + + def read_remote_pkg_list(list_path) + @support_os_list.each do |os| + filename = PKG_LIST_FILE_PREFIX + os + local_file_path = File.join(list_path, filename) + if File.exist? local_file_path then + begin + pkg_hash = Parser.read_repo_pkg_list_from local_file_path + @pkg_hash_os[os] = pkg_hash + @log.info "Get package information for #{os}.. OK" + rescue => e + @log.error( e.message, Log::LV_USER) + @pkg_hash_os[os] = {} + end + else + @log.warn "Failed to read pkg_list_#{os} file" + @pkg_hash_os[os] = {} + end + end + end + + def read_supported_os_list(list_path) + local_file_path = File.join(list_path, OS_INFO_FILE) + if File.exist? local_file_path then + File.open(local_file_path, "r") do |f| + f.each_line do |l| + os = l.strip + if @support_os_list.index(os).nil? then @support_os_list.push(os) end + end + end + @log.info "Get supported os infomation.. OK" + else + @log.warn "Failed to get supported os infomation" + end + end + + def download_os_list(from_server, dist = nil) + if dist.nil? then dist = get_pkglist_path end + file_url = File.join(@server_addr, OS_INFO_FILE) + if from_server then + if not FileDownLoader.download(file_url, dist, @log) then return false end + else + if File.exist? file_url then FileUtils.cp(file_url, dist) + else return false end + end + + return true + end + + def read_archive_pkg_list(list_path) + local_file_path = File.join(list_path, ARCHIVE_PKG_LIST_FILE) + if File.exist? local_file_path then + File.open(local_file_path, "r") do |f| + f.each_line do |l| + pkg = l.strip + if @archive_pkg_list.index(pkg).nil? then @archive_pkg_list.push(pkg) end + end + end + @log.info "Get archive package infomation.. OK" + else + @log.warn "Failed to get archive package infomation" + end + end + + def download_archive_pkg_list(from_server, dist = nil) + if dist.nil? then dist = get_pkglist_path end + file_url = File.join(@server_addr, @snapshot_path, ARCHIVE_PKG_LIST_FILE) + if from_server then + if not FileDownLoader.download(file_url, dist, @log) then return false end + else + if File.exist? file_url then FileUtils.cp(file_url, dist) + else return false end + end + + return true + end + + def download_pkg_list(from_server, dist = nil) + if dist.nil? then dist = get_pkglist_path end + @support_os_list.each do |os| + filename = PKG_LIST_FILE_PREFIX + os + file_url = File.join(@server_addr, @snapshot_path, filename) + if from_server then + if not FileDownLoader.download(file_url, dist, @log) then return false end + else + if File.exist? file_url then FileUtils.cp(file_url, dist) + else return false end + end + end + + return true + end + + private + # create installed package hash + def read_installed_pkg_list() + + config_path = File.join(@location, PACKAGE_INFO_DIR) + if not File.directory? config_path then return end + + installed_pkg_hash_key = get_installed_pkg_list_file_path() + if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then return + else + file_path = installed_pkg_hash_key + if not File.exist? file_path then + #raise RuntimeError, "#{file_path} file does not exist" + return + end + begin + pkg_hash = Parser.read_repo_pkg_list_from file_path + rescue => e + @log.error( e.message, Log::LV_USER) + return + end + @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash + end + end + + private + # check to exist installed package list file + def check_installed_pkg_list_file() + + if @location.nil? then raise RuntimeError, "#{@location} path does not exist" end + file_path = get_installed_pkg_list_file_path() + if File.exist? file_path then return true + else return false end + end + + private + # get installed package list file path + def get_installed_pkg_list_file_path() + + file_full_path = File.join(@location, PACKAGE_INFO_DIR, INSTALLED_PKG_LIST_FILE) + return file_full_path + end + + private + # write package hash to file + def write_pkg_hash_to_file(pkg_hash) + + file_path = get_installed_pkg_list_file_path() + if pkg_hash.nil? then + pkg_hash = @installed_pkg_hash_loc[file_path] + end + if not pkg_hash.nil? then + config_path = File.join(@location, PACKAGE_INFO_DIR) + if not File.exist? config_path then FileUtils.mkdir_p "#{config_path}" end + if File.exist? file_path then File.delete(file_path) end + File.open(file_path, "a+") do |file| + pkg_list = pkg_hash.values + pkg_list.each do |pkg| + pkg.print_to_file(file) + file.puts "\n" + end + end + end + @log.info "Write package informations to \"#{file_path}\".. OK" + end + + private + def check_meta_pkg(pkg_name, os) + if not check_remote_pkg(pkg_name, os) then return false end + + attr = get_attr_from_pkg(pkg_name, os, "attribute") + if attr.nil? or attr.empty? then return false end + if attr[0].strip.upcase.eql? "META" then return true + else return false end + end end diff --git a/src/pkg_server/clientOptParser.rb b/src/pkg_server/clientOptParser.rb index ae12c36..fff8924 100644 --- a/src/pkg_server/clientOptParser.rb +++ b/src/pkg_server/clientOptParser.rb @@ -1,5 +1,5 @@ =begin - + clientOptParser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -30,194 +30,177 @@ require 'optparse' $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" require "utils" -def set_default( options ) +def set_default( options ) if options[:t].nil? then options[:t] = false end if options[:f].nil? then options[:f] = false end if options[:v].nil? then options[:v] = false end end def option_error_check( options ) - $log.info "option error check" case options[:cmd] - when "update" then - - when "clean" then - - when "upgrade" then + when "update" then - when "check-upgrade" then + when "clean" then - when "download" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli download -p [-o ] [-l ] [-u ] [-t]" - end + when "upgrade" then - when "upload" then - if options[:alias].nil? or options[:alias].empty? or\ - options[:id].nil? or options[:id].empty? or \ - options[:srcpkg].nil? or options[:srcpkg].empty? then - raise ArgumentError, "Usage: pkg-cli upload -a -i -s [-b ]" - end + when "check-upgrade" then - when "source" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli source -p [-o ] [-l ] [-u ]" - end + when "download" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli download -P [-o ] [-l ] [-u ] [--trace]" + end - when "install" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli install -p [-o ] [-l ] [-u ] [-t] [-f]" - end + when "install" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli install -P [-o ] [-l ] [-u ] [--trace] [--force]" + end - when "install-file" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli install-lpkg -p [-l ] [-f]" - end + when "install-file" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli install-lpkg -P [-l ] [-u ] [--trace] [--force]" + end - when "uninstall" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli uninstall -p [-l ] [-t]" - end + when "uninstall" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli uninstall -P [-l ] [--trace]" + end - when "show-rpkg" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli show-rpkg -p [-o ] [-u ]" - end + when "show-rpkg" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli show-rpkg -P [-o ] [-u ]" + end - when "list-rpkg" then + when "list-rpkg" then - when "show-lpkg" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli show-lpkg -p [-l ]" - end + when "show-lpkg" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli show-lpkg -P [-l ]" + end - when "list-lpkg" then + when "list-lpkg" then - when "build-dep" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli build-dep -p [-o ]" - end + when "build-dep" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli build-dep -P [-o ]" + end - when "install-dep" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli install-dep -p [-o ]" - end + when "install-dep" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli install-dep -P [-o ]" + end else - raise ArgumentError, "input option incorrect : #{options[:cmd]}" + raise ArgumentError, "Input is incorrect : #{options[:cmd]}" end end -def option_parse - options = {} - optparse = OptionParser.new do|opts| - # Set a banner, displayed at the top - # of the help screen. - opts.banner = "Usage: pkg-cli {update|clean|download|source|install|uninstall|upgrade|rpkg-show|rpkg-list|lpkg-show|lpkg-list|build-dep|install-dep|help} ..." + "\n" \ - + "\t" + "pkg-cli update [-u ]" + "\n" \ - + "\t" + "pkg-cli clean [-l ] [-f]" + "\n" \ - + "\t" + "pkg-cli download -p [-o ] [-l ] [-u ] [-t]" + "\n" \ - + "\t" + "pkg-cli upload -a -i -s [-b [-o ] [-l ] [-u ]" + "\n" \ - + "\t" + "pkg-cli install -p [-o ] [-l ] [-u ] [-t] [-f]" + "\n" \ - + "\t" + "pkg-cli install-file -p [-l ] [-f]" + "\n" \ - + "\t" + "pkg-cli uninstall -p [-l ] [-t]" + "\n" \ - + "\t" + "pkg-cli upgrade [-l ] [-o ] [-u ] [-t]" + "\n" \ - + "\t" + "pkg-cli check-upgrade [-l ] [-o ] [-u ]" + "\n" \ - + "\t" + "pkg-cli show-rpkg -p [-o ] [-u ]" + "\n" \ - + "\t" + "pkg-cli list-rpkg [-o ] [-u ]" + "\n" \ - + "\t" + "pkg-cli show-lpkg -p [-l ]" + "\n" \ - + "\t" + "pkg-cli list-lpkg [-l ]" + "\n" \ - + "\t" + "pkg-cli build-dep -p [-o ]" + "\n" \ - + "\t" + "pkg-cli install-dep -p [-o ]" + "\n" \ - - opts.on( '-p', '--pkg ', 'package name or package file name' ) do |name| - options[:pkg] = name - end - - opts.on( '-o', '--os ', 'target operating system' ) do |os| - options[:os] = os - end - - opts.on( '-u', '--url ', 'package server url' ) do|url| - options[:url] = url - end - - opts.on( '-a', '--alias ', 'ssh alias' ) do|al| - options[:alias] = al - end - - opts.on( '-i', '--id ', 'id' ) do|id| - options[:id] = id - end - - opts.on( '-l', '--loc ', 'location' ) do |loc| - options[:loc] = loc - end - - opts.on( '-s', '--src ', 'source package path' ) do|src| - options[:srcpkg] = [] - list = src.tr(" \t","").split(",") - list.each do |l| - if l.start_with? "~" then l = Utils::HOME + l.delete("~") end - options[:srcpkg].push l - end - end - - opts.on( '-t', '--trace', 'enable trace dependent packages' ) do - options[:t] = true - end - - opts.on( '-b', '--bin ', 'binary package path' ) do|bin| - options[:binpkg] = [] - list = bin.tr(" \t","").split(",") - list.each do |l| - if l.start_with? "~" then l = Utils::HOME + l.delete("~") end - options[:binpkg].push l - end - end - - opts.on( '-f', '--force', 'enable force' ) do - options[:f] = true - end - - opts.on( '-h', '--help', 'display this information' ) do - puts opts +def option_parse + options = {} + banner = "Requiest service to package-server and control packages service command-line tool." + "\n" \ + + "\n" + "Usage: pkg-cli [OPTS] or pkg-cli (-h|-v)" + "\n" \ + + "\n" + "Subcommands:" + "\n" \ + + "\t" + "update Update to the latest package in your SDK environment." + "\n" \ + + "\t" + "clean Delete the package in your SDK environment." + "\n" \ + + "\t" + "download Download the package in your SDK environment." + "\n" \ + + "\t" + "install Download the package from package-server and install the package in your SDK environment." + "\n" \ + + "\t" + "install-file Install the package in your SDK environment." + "\n" \ + + "\t" + "uninstall Uninstall the package in your SDK environment." + "\n" \ + + "\t" + "upgrade Upgrade your SDK environment." + "\n" \ + + "\t" + "check-upgrade Check packages to upgrade." + "\n" \ + + "\t" + "show-rpkg Show the package in the package-server." + "\n" \ + + "\t" + "list-rpkg Show the all packages in the package-server." + "\n" \ + + "\t" + "show-lpkg Show the package in your SDK environment." + "\n" \ + + "\t" + "list-lpkg Show the all packages in your SDK environment." + "\n" \ + + "\t" + "build-dep Show build-dependency packages" + "\n" \ + + "\t" + "install-dep Show install-dependency packages" + "\n" \ + + "\n" + "Subcommand usage:" + "\n" \ + + "\t" + "pkg-cli update [-u ]" + "\n" \ + + "\t" + "pkg-cli clean [-l ] [--force]" + "\n" \ + + "\t" + "pkg-cli download -P [-o ] [-l ] [-u ] [--trace]" + "\n" \ + + "\t" + "pkg-cli install -P [-o ] [-l ] [-u ] [--trace] [--force]" + "\n" \ + + "\t" + "pkg-cli install-file -P [-l ] [-u ] [--trace] [--force]" + "\n" \ + + "\t" + "pkg-cli uninstall -P [-l ] [--trace]" + "\n" \ + + "\t" + "pkg-cli upgrade [-l ] [-o ] [-u ] [--trace]" + "\n" \ + + "\t" + "pkg-cli check-upgrade [-l ] [-o ] [-u ]" + "\n" \ + + "\t" + "pkg-cli show-rpkg -P [-o ] [-u ]" + "\n" \ + + "\t" + "pkg-cli list-rpkg [-o ] [-u ]" + "\n" \ + + "\t" + "pkg-cli show-lpkg -P [-l ]" + "\n" \ + + "\t" + "pkg-cli list-lpkg [-l ]" + "\n" \ + + "\t" + "pkg-cli build-dep -P [-o ]" + "\n" \ + + "\t" + "pkg-cli install-dep -P [-o ]" + "\n" \ + + "\n" + "Options:" + "\n" + + optparse = OptionParser.new(nil, 32, ' '*8) do|opts| + # Set a banner, displayed at the top + # of the help screen. + + opts.banner = banner + + opts.on( '-P', '--pkg ', 'package name or package file name' ) do |name| + options[:pkg] = name + end + + opts.on( '-o', '--os ', 'target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64' ) do |os| + options[:os] = os + end + + opts.on( '-u', '--url ', 'package server url: http://127.0.0.1/dibs/unstable' ) do |url| + options[:url] = url + end + + opts.on( '-l', '--loc ', 'install/download location' ) do |loc| + options[:loc] = loc + end + + opts.on( '--trace', 'enable trace dependent packages' ) do + options[:t] = true + end + + opts.on( '--force', 'enable force' ) do + options[:f] = true + end + + opts.on( '-h', '--help', 'display help' ) do + puts opts exit - end - - end - - $log.info "option parsing start" - $log.info "option is : " + ARGV * "," - - cmd = ARGV[0] - if cmd.eql? "update" or cmd.eql? "download" or \ - cmd.eql? "install" or cmd.eql? "show-rpkg" or \ - cmd.eql? "list-rpkg" or cmd.eql? "source" or \ - cmd.eql? "uninstall" or cmd.eql? "show-lpkg" or \ - cmd.eql? "list-lpkg" or cmd.eql? "upload" or \ - cmd.eql? "install-file" or cmd.eql? "clean" or \ - cmd.eql? "upgrade" or cmd.eql? "check-upgrade" or \ - cmd.eql? "build-dep" or cmd.eql? "install-dep" or \ - cmd =~ /(help)|(-h)|(--help)/ then - if cmd.eql? "help" then ARGV[0] = "-h" end - options[:cmd] = ARGV[0] - else - raise ArgumentError, "first paramter must be {update|clean|download|upload|source|install|install-file|uninstall|upgrade|check-upgrade|show-rpkg|list-rpkg|show-lpkg|list-lpkg|build-dep|install-dep|help} : your input is #{ARGV[0]}" - end - - optparse.parse! - - $log.info "option parsing end" + end + + opts.on( '-v', '--version', 'display version' ) do + puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version() + exit + end + end + + cmd = ARGV[0] + if cmd.eql? "update" or cmd.eql? "download" or + cmd.eql? "install" or cmd.eql? "show-rpkg" or + cmd.eql? "list-rpkg" or + cmd.eql? "uninstall" or cmd.eql? "show-lpkg" or + cmd.eql? "list-lpkg" or + cmd.eql? "install-file" or cmd.eql? "clean" or + cmd.eql? "upgrade" or cmd.eql? "check-upgrade" or + cmd.eql? "build-dep" or cmd.eql? "install-dep" or + cmd =~ /(-v)|(--version)/ or + cmd =~ /(help)|(-h)|(--help)/ then + + if cmd.eql? "help" then + V[0] = "-h" + end + options[:cmd] = ARGV[0] + else + raise ArgumentError, "Usage: pkg-cli [OPTS] or pkg-cli -h" + end + + optparse.parse! set_default options - # option error check + # option error check option_error_check options - return options -end + return options +end diff --git a/src/pkg_server/distribution.rb b/src/pkg_server/distribution.rb index 09f8da1..5aa613b 100644 --- a/src/pkg_server/distribution.rb +++ b/src/pkg_server/distribution.rb @@ -1,6 +1,6 @@ =begin - - distribution.rb + + distribution.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -29,75 +29,88 @@ Contributors: require 'fileutils' $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" require "parser" +require "installer" -class Distribution - attr_accessor :name, :location, :server_url +class Distribution + attr_accessor :name, :location, :server_url, :lock_file_path, :last_sync_changes - # constant - SUPPORTED_OS = ["linux", "windows", "darwin"] - PKG_LIST_FILE_PREFIX = "pkg_list_" - ARCHIVE_PKG_LIST = "archive_pkg_list" + # constant + PKG_LIST_FILE_PREFIX = "pkg_list_" + ARCHIVE_PKG_FILE = "archive_pkg_list" + OS_INFO_FILE = "os_info" + SNAPSHOT_INFO_FILE = "snapshot.info" + LOCK_FILE = ".lock_file" + SYNC_LOCK_FILE = ".sync_lock_file" - def initialize (name, location, server_url, log) + def initialize( name, location, server_url, pkg_server ) @name = name @location = location - @pkg_hash_os = {} - @log = log @server_url = server_url + @log = pkg_server.log + @integrity = pkg_server.integrity + @lock_file_path = "#{location}/#{LOCK_FILE}" + @sync_lock_file_path = "#{location}/#{SYNC_LOCK_FILE}" + @pkg_hash_os = {} + @archive_pkg_list = [] + @snapshot_hash = [] + @support_os_list = [] + @last_sync_changes = "" + @log.info "Distribution class[#{name}] initialize " - for os in SUPPORTED_OS - if @location.empty? or ( not File.exist? "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" ) then - @pkg_hash_os[os] = {} - else - @pkg_hash_os[os] = Parser.read_pkg_list( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" ) - end - end + initialize_pkg_list() end - def register (file_path, pkg) - @log.info "Distribution class's register" + def register (file_path, pkg, internal_flag) if pkg.nil? then raise RuntimeError, "package file does not contain pkginfo.manifest: [#{file_path}]" end + if not @pkg_hash_os.has_key?(pkg.os) then + raise RuntimeError, "package server does not support package's os : [#{pkg.os}]" + end + exist_pkg = @pkg_hash_os[pkg.os][pkg.package_name] - + # version check and if existing version is higher then upload version? - if not exist_pkg.nil? - if not ( Utils.compare_version( exist_pkg.version, pkg.version ).eql? 1 ) then - raise RuntimeError, "existing package's version is higher than register package" + if (not exist_pkg.nil?) and (not internal_flag) then + if Utils.compare_version( exist_pkg.version, pkg.version ) != 1 then + raise RuntimeError, "existing package's version is higher then register package : [#{pkg.package_name}] in [#{pkg.os}]" end end # modified pkg class - pkg.origin = "local" - pkg.source = "" + pkg.origin = "local" + pkg.source = "" pkg.path = "/binary/" + File.basename( file_path ) - # TODO: windows and mac : sha256sum - if Utils::HOST_OS.eql? "linux" then - pkg.checksum = `sha256sum #{file_path}`.split(" ")[0] - end - pkg.size = `du -b #{file_path}`.split[0].strip + if pkg.checksum.empty? then + # TODO: windows and mac : sha256sum + if Utils.is_unix_like_os( Utils::HOST_OS ) then + pkg.checksum = `sha256sum #{file_path}`.split(" ")[0] + end + end + + if pkg.size.empty? then + pkg.size = `du -b #{file_path}`.split[0].strip + end + + @pkg_hash_os[pkg.os][pkg.package_name] = pkg - @pkg_hash_os[pkg.os][pkg.package_name] = pkg - return pkg end def register_for_test (file_path, pkg) - @log.info "Distribution class's register for test" if pkg.nil? then raise RuntimeError, "package file does not contain pkginfo.manifest: [#{file_path}]" end # modified pkg class - pkg.origin = "local" - pkg.source = "" + pkg.origin = "local" + pkg.source = "" pkg.path = "/temp/" + File.basename( file_path ) # TODO: windows and mac : sha256sum - if Utils::HOST_OS.eql? "linux" then + if Utils.is_unix_like_os( Utils::HOST_OS ) then pkg.checksum = `sha256sum #{file_path}`.split(" ")[0] end pkg.size = `du -b #{file_path}`.split[0].strip @@ -105,393 +118,837 @@ class Distribution return pkg end - def generate_snapshot (name, base_snapshot, append_pkg_list) - @log.info "Distribution class's generate snapshot" + def register_archive_pkg( archive_pkg ) + if not @archive_pkg_list.include? archive_pkg then + @archive_pkg_list.push archive_pkg + else + @log.error("archive package already exist : [#{archive_pkg}]", Log::LV_USER) + end + end + + def generate_snapshot(name, base_snapshot, from_cmd, change_log_string) # if name is nil or empty then create uniq name if name.nil? or name.empty? then name = Utils.create_uniq_name end - # check base snapshot exist - if File.exist? "#{@location}/snapshots/#{name}" then + # check base snapshot exist + if File.exist? "#{@location}/snapshots/#{name}" then raise "Snapshot is already exist: #{name}" end - if base_snapshot.nil? then base_snapshot = "" else base_snapshot.strip! end - if append_pkg_list.nil? then append_pkg_list = [] end + FileUtils.mkdir "#{@location}/snapshots/#{name}" + FileUtils.mkdir "#{@location}/changes" if not File.exists? "#{@location}/changes" + File.open( "#{@location}/changes/#{name}.log","w") { |f| f.puts change_log_string } + + # base_snapshot_path + if base_snapshot.empty? then + snapshot_path = @location + else + snapshot_path = "#{@location}/snapshots/#{base_snapshot.strip}" + end - if base_snapshot.empty? and append_pkg_list.empty? then - FileUtils.mkdir "#{@location}/snapshots/#{name}" + # copy package list + @support_os_list.each do |os| + FileUtils.copy_file( "#{snapshot_path}/#{PKG_LIST_FILE_PREFIX}#{os}", + "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{os}" ) + end - for os in SUPPORTED_OS - FileUtils.copy( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", - "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{os}" ) - end + # copy archive package list + FileUtils.copy_file( "#{snapshot_path}/#{ARCHIVE_PKG_FILE}", + "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_FILE}" ) - # copy archive package list - begin - FileUtils.copy( "#{@location}/#{ARCHIVE_PKG_LIST}", "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_LIST}" ) - rescue => e - @log.warn "ARCHIVE_PKG_LIST not exist" - end + # copy os info file + FileUtils.copy_file( "#{snapshot_path}/#{OS_INFO_FILE}", + "#{@location}/snapshots/#{name}/#{OS_INFO_FILE}" ) + # generate temp file + tmp_file_name = "" + while ( tmp_file_name.empty? ) + tmp_file_name = @location + "/temp/." + Utils.create_uniq_name - @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER) - # base_snapshot is exist - elsif not ( base_snapshot.empty? ) then - FileUtils.mkdir "#{@location}/snapshots/#{name}" - - for os in SUPPORTED_OS - # check base snapshot exist - if (not File.exist? "#{@location}/snapshots/#{base_snapshot}/#{PKG_LIST_FILE_PREFIX}#{os}") then - raise RuntimeError, "Can't find base snapshot [#{base_snapshot}]" - end - - base_pkg_list = Parser.read_pkg_list( "#{@location}/snapshots/#{base_snapshot}/#{PKG_LIST_FILE_PREFIX}#{os}" ) - snapshot_generate2( name, os, base_pkg_list, append_pkg_list ) + if File.exist? tmp_file_name then + tmp_file_name = "" end - - # copy archive package list - begin - FileUtils.copy( "#{@location}/#{ARCHIVE_PKG_LIST}", "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_LIST}" ) - rescue => e - @log.warn "ARCHIVE_PKG_LIST not exist" + end + + FileUtils.copy_file( "#{@location}/#{SNAPSHOT_INFO_FILE}", tmp_file_name ) + File.open( tmp_file_name, "a" ) do |f| + f.puts "name : #{name}" + f.puts "time : #{Time.now.strftime("%Y%m%d%H%M%S")}" + if from_cmd then + f.puts "type : manual" + else + f.puts "type : auto" end + f.puts "path : /snapshots/#{name}" + f.puts + end + FileUtils.mv( tmp_file_name, "#{@location}/#{SNAPSHOT_INFO_FILE}", :force => true ) + + # snapshot is generated + @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER) + return name + end - @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER) - # base_snapshot is empty - else - FileUtils.mkdir "#{@location}/snapshots/#{name}" + def sync(force, snapshot = "") + pkg_list_update_flag = false + archive_update_flag = false + distribution_update_flag = false + changes = [] + + # lock + sync_lock_file = Utils.file_lock(@sync_lock_file_path) - for os in SUPPORTED_OS - base_pkg_list = Parser.read_pkg_list( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" ) - snapshot_generate2( name, os, base_pkg_list, append_pkg_list ) - end + # reload pkg list from newest pkg list file + reload_distribution_information() - # copy archive package list - begin - FileUtils.copy( "#{@location}/#{ARCHIVE_PKG_LIST}", "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_LIST}" ) - rescue => e - @log.warn "ARCHIVE_PKG_LIST not exist" - end + # check distribution's server_url + if @server_url.empty? then + @log.error("This distribution has not remote server") + Utils.file_unlock(sync_lock_file) + raise RuntimeError, "remote server address empty" + end - @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER) + # generate client class + if snapshot.nil? or snapshot.empty? then + server_url = @server_url + else + server_url = "#{@server_url}/snapshots/#{snapshot}" end - end + client = Client.new( server_url, "#{@location}/binary", @log ) - def snapshot_generate2( name, os, pkg_list, append_pkg_list ) - @log.info "snapshot_generate2: input append_pkg_list #{append_pkg_list}" - append_pkg_list.each do |pkg| - # os check - if pkg.os.eql? os.strip then pkg_list[pkg.package_name] = pkg end + # parents package server check + if client.pkg_hash_os.keys.empty? then + @log.error("Sync process stopped by error.") + @log.error("Parents package server does not have [[os_info]] file.") + + Utils.file_unlock(sync_lock_file) + raise RuntimeError, "Parents package server does not have [[os_info]] file." end - - File.open( "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f| - pkg_list.each_value do |pkg| - pkg.print_to_file(f) - f.puts + + # update os list + add_os_list = client.support_os_list - @support_os_list + add_os_list.each do |os| + add_os(os) + changes.push "Add OS #{os}" + pkg_list_update_flag = true + end + + if force then + remove_os_list = @support_os_list - client.support_os_list + remove_os_list.each do |os| + remove_os(os) + changes.push "Remove OS #{os}" + pkg_list_update_flag = true end - end - end + end + update_pkg_list = [] - def sync( force, os ) + @support_os_list.each do |os| + # error check + if client.pkg_hash_os[os].nil? then + @log.error("os[[#{os}]] is removed in parents package server", Log::LV_USER) + next + end - # check distribution's server_url - if @server_url.empty? then - @log.error( "This distribution has not remote server" , Log::LV_USER) - return + server_pkg_name_list = client.pkg_hash_os[os].keys + local_pkg_name_list = @pkg_hash_os[os].keys + full_pkg_name_list = server_pkg_name_list + local_pkg_name_list + full_pkg_name_list.uniq! + + full_pkg_name_list.each do |pkg_name| + ret = sync_package( pkg_name, client, os, force ) + if not ret.nil? then + update_pkg_list.push(ret) + pkg_list_update_flag = true + end + end end - # generate client class - client_bin = Client.new( @server_url, "#{@location}/binary", @log ) - client_bin.update - client_src = Client.new( @server_url, "#{@location}/source", @log ) - client_src.update - - source_pkg_path_list = [] - dep_pkg_path_list = [] - - # error check - if client_bin.pkg_hash_os[os].nil? then - raise "Package list can't generated. url is #{@server_url}. os is #{os}" - end - - # check existing source package list - @pkg_hash_os[os].each_value do |pkg| - if not source_pkg_path_list.include? pkg.src_path then - source_pkg_path_list.push pkg.src_path - end - end - - full_pkg_list = client_bin.pkg_hash_os[os].merge(@pkg_hash_os[os]) - - full_pkg_list.each_key do |pkg_name| - server_pkg = client_bin.pkg_hash_os[os][pkg_name] - local_pkg = @pkg_hash_os[os][pkg_name] - - # if server and local has package - if ( not server_pkg.nil? ) and ( not local_pkg.nil? ) then - # if server version is not updated then skip - if not ( Utils.compare_version( local_pkg.version, server_pkg.version ).eql? 1 ) then - @log.info "existing packages version equal or higher then server's version so package[#{pkg_name}] skip" - @log.info "server package version: [#{server_pkg.version}]" - @log.info "local package version: [#{local_pkg.version}]" - - next - end + # sync archive package + update_archive_list = sync_archive_pkg() - # if server version is not updated then skip - # if server's pakcage is local package and mode is not force then local package will be upaded - if ( local_pkg.origin.eql? "local" ) and ( not force ) then - @log.info "package [#{pkg_name}] is local package. so skip update" - - next - end - - # package update - @log.info "update package from server: [#{pkg_name}]" - file_path_list = client_bin.download( pkg_name, os, false ) - - # file download error check - if file_path_list.nil? or file_path_list.empty? then - @log.error( "Can't download package file #{pkg_name}" , Log::LV_USER) - next - else - @log.info "download binary package successfully: [#{pkg_name}]" - file_path = file_path_list[0] - end - - # update pkg class - server_pkg.path = "/binary/#{File.basename(file_path)}" - server_pkg.origin = client_bin.server_addr - @pkg_hash_os[os][pkg_name] = server_pkg - - dep_pkg_path_list = dep_pkg_path_list + server_pkg.source_dep_list - - # if binary only package, then skip downloading its source - if server_pkg.src_path.empty? then next end - - # if binary's source package is not downlaoded, download it - if ( not source_pkg_path_list.include? server_pkg.src_path ) then - @log.info "download source package: [#{server_pkg.src_path}]" - file = client_src.download_source( pkg_name, os ) - if file.nil? then - @log.error "Can't download source package [#{pkg_name}]" + # lock + lock_file = Utils.file_lock(@lock_file_path) + + # reload pkg list from newest pkg list file + reload_distribution_information() + + # update pkg_list hash + update_pkg_list.each do |update_option, os, pkg| + # if updated package's os is removed then skip update + if not @support_os_list.include? os then + next + end + + case update_option + when "ADD" + local_pkg = @pkg_hash_os[os][pkg.package_name] + + if (not force) and (not local_pkg.nil?) then + # if updated package 'local' package then skip + if local_pkg.origin.eql? "local" then + next + end + + # if package is update when sync time then skip + if Utils.compare_version(local_pkg.version, pkg.version) == -1 then + next else - source_pkg_path_list.push server_pkg.src_path - end - end - # if package exist only server - elsif ( not server_pkg.nil? ) then - #downnlaod binary package - file_path_list = client_bin.download( pkg_name, os, false ) - - # file download error check - if file_path_list.nil? or file_path_list.empty? then - @log.error( "Can't download package file #{pkg_name}", Log::LV_USER) - next - else - @log.info "download binary package successfully: [#{pkg_name}]" - file_path = file_path_list[0] - end - - # update pkg class - server_pkg.path = "/binary/#{File.basename(file_path)}" - server_pkg.origin = client_bin.server_addr - @pkg_hash_os[os][pkg_name] = server_pkg - - dep_pkg_path_list = dep_pkg_path_list + server_pkg.source_dep_list - - # if binary only package, then skip downloading its source - if server_pkg.src_path.empty? then next end - - # if binary's source package is not downlaoded, download it - if not source_pkg_path_list.include? server_pkg.src_path then - @log.info "download source package: [#{server_pkg.src_path}]" - file = client_src.download_source( pkg_name, os ) - if file.nil? - @log.error "Can't download source package [#{server_pkg.src_path}]" - else - source_pkg_path_list.push server_pkg.src_path + @log.info( "update package [#{pkg.package_name}] in #{pkg.os}", Log::LV_USER) end end - # if package exist only local - elsif ( not local_pkg.nil? ) then - # if pakcage is not local package then server's package is removed - # so, local package remove - if not local_pkg.origin.eql? "local" then - @pkg_hash_os[os].delete(pkg_name) + + @pkg_hash_os[os][pkg.package_name] = pkg + changes.push "Package: #{pkg.package_name} changes: #{pkg.get_changes}" if pkg.does_change_exist? + when "REMOVE" + if not force then + if @pkg_hash_os[os][pkg.package_name].origin.eql? "local" then + else + @log.info( "remove package [#{pkg.package_name}] in #{pkg.os}", Log::LV_USER) + next + end end + + @pkg_hash_os[os].delete(pkg.package_name) + changes.push "#{pkg.package_name} #{os} removed" else - raise RuntimeError,"hash merge error!" + @log.error("Unsupportd update option : #{update_option}", Log::LV_USER) + next + end + end + + update_archive_list.each do |pkg| + if not @archive_pkg_list.include? pkg then + @archive_pkg_list.push pkg + changes.push "Add archive package #{pkg}" + archive_update_flag = true end end - @log.info "pkg file update end" - # download dependency source packages - dep_pkg_path_list.uniq.each do |dep| - if dep.package_name.strip.empty? then next end - @log.info "download dep package: [#{dep.package_name}]" - file = client_src.download_dep_source( dep.package_name ) - if file.nil? - @log.error "Can't download dep package [#{dep.package_name}]" - end - end + # update pkg_list file + if pkg_list_update_flag then + write_all_pkg_list() + distribution_update_flag = true + end + + # update archive list file + if archive_update_flag then + write_archive_pkg_list() + distribution_update_flag = true + end + + # unlock + Utils.file_unlock(lock_file) + Utils.file_unlock(sync_lock_file) + + if not changes.empty? then + @last_sync_changes = "SYSTEM: sync parents server \n#{changes.uniq.join("\n\n")}" + end - @log.info "pkg deb file update end" - # pakcage list file update - write_pkg_list(os) - @log.info "write pkg list" + return distribution_update_flag end - def sync_archive_pkg - client = Client.new( @server_url, "#{@location}/source", @log ) - client.update - - downloaded_list = [] - client.archive_pkg_list.each do |pkg| - if not File.exist? "#{@location}/source/#{pkg}" then - file = client.download_dep_source(pkg) - if file.nil? - @log.error "Can't download archive package [#{file}]" - else - downloaded_list.push pkg + def add_os(os) + if @support_os_list.include? os then + @log.error("#{os} is already exist ", Log::LV_USER) + return + end + + # update os information + @support_os_list.push os + @pkg_hash_os[os] = {} + File.open("#{@location}/#{OS_INFO_FILE}", "a") do |f| + f.puts os + end + + # create pkg_list_#{os} file + File.open( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f| end + end + + def clean( remain_snapshot_list ) + file_list = [] + used_archive_list = [] + + # collect remaining file's name from current package server version + @support_os_list.each do |os| + @pkg_hash_os[os].each_value do |pkg| + file_list.push(pkg.path.sub("/binary/","")) + + pkg.source_dep_list.each do |source_dep| + if @archive_pkg_list.include? source_dep.package_name then + used_archive_list.push source_dep.package_name + else + @log.error("Can't find dependency source package : #{source_dep.package_name}") + end end end - end + end + + # remain only used archive package + @archive_pkg_list = used_archive_list.uniq + write_archive_pkg_list + + # collect remaning file's name from snapshot list + remain_snapshot_list.each do |snapshot| + os_info = "#{@location}/snapshots/#{snapshot}/#{OS_INFO_FILE}" + os_list = [] + # if snapshot has os_info file then using that file + if File.exist? os_info + File.open( os_info, "r" ) do |f| + f.each_line do |l| + os_list.push l.strip + end + end + # if snapshot does not have os_info file then using package server os_info list + else + os_list = @support_os_list + end + + os_list.each do |os| + begin + info_file = "#{@location}/snapshots/#{snapshot}/#{PKG_LIST_FILE_PREFIX}#{os}" + if not File.exist? info_file then + @log.error( "pkg list file does not exist : #{info_file}", Log::LV_USER) + next + end + + pkg_list = Parser.read_repo_pkg_list_from(info_file) + + pkg_list.each_value do |pkg| + file_list.push(pkg.path.sub("/binary/","")) + end + rescue => e + @log.error( e.message, Log::LV_USER) + end + end + + used_archive_list = used_archive_list + read_archive_pkg_list( snapshot ) + end + + file_list.uniq! + used_archive_list.uniq! + + # remove unused binary file + Dir.new( @location + "/binary" ).each do |file| + if file.start_with? "." then next end + + if not file_list.include? file then + FileUtils.rm "#{@location}/binary/#{file}" + end + end + + # remove unused archive file + Dir.new( @location + "/source" ).each do |file| + if file.start_with? "." then next end + + if not used_archive_list.include? file then + FileUtils.rm "#{@location}/source/#{file}" + end + end + + # remove unused snapshot + Dir.new( @location + "/snapshots" ).each do |snapshot| + if snapshot.start_with? "." then next end + + if not remain_snapshot_list.include? snapshot then + FileUtils.rm_rf "#{@location}/snapshots/#{snapshot}" + end + end + + # upate snapshot.info file + update_snapshot_info_file(remain_snapshot_list) + end - write_archive_pkg_list( downloaded_list ) - end + def write_all_pkg_list + @support_os_list.each do |os| + write_pkg_list(os) + end + end def write_pkg_list( os ) - File.open( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f| + # if input os is empty then return + if os.nil? or os.empty? then return end + + # generate temp file + tmp_file_name = "" + while ( tmp_file_name.empty? ) + tmp_file_name = @location + "/temp/." + Utils.create_uniq_name + + if File.exist? tmp_file_name then + tmp_file_name = "" + end + end + + File.open( tmp_file_name, "w" ) do |f| @pkg_hash_os[os].each_value do |pkg| + # insert package information to file pkg.print_to_file(f) - f.puts + # insert empty line to file + f.puts end - end - end + end - def write_archive_pkg_list( pkg_file_name_list ) - File.open( "#{@location}/#{ARCHIVE_PKG_LIST}", "a" ) do |f| - pkg_file_name_list.map { |name| f.puts(name) } - end + FileUtils.mv( tmp_file_name, "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", :force => true ) end - # input: package file path(zip file) - # return: pkg + # input: package file path(zip file) + # return: pkg def get_package_from_file(file_path) - tmp_dir = "./" + Utils.create_uniq_name - FileUtils.mkdir "#{@location}/#{tmp_dir}" - - # file extention is zip - if file_path.end_with? ".zip" then - system("unzip -q #{file_path} pkginfo.manifest -d #{@location}/#{tmp_dir} ") - # file extention is tar.gz - elsif file_path.end_with? ".tar.gz" or file_path.end_with? ".tar" then - system("tar -xzf #{file_path} -C #{@location}/#{tmp_dir}") + tmp_dir = @location + "/" + Utils.create_uniq_name + + #if file extension is .zip then check pkginfo.manifest + if File.extname(file_path).eql? ".zip" then + FileUtils.mkdir tmp_dir + + ret = FileInstaller.extract_a_file(file_path, "pkginfo.manifest", tmp_dir, @log) else - raise "unsupported zipping file. just use [zip/tar.gz]" + return nil end - pkg = Parser.read_pkginfo( "#{@location}/#{tmp_dir}/pkginfo.manifest" ) - FileUtils.rm_rf "#{@location}/#{tmp_dir}" - return pkg - end + # if pkginfo.manifest file exist + if not ret.nil? then + begin + pkg = Parser.read_single_pkginfo_from "#{tmp_dir}/pkginfo.manifest" + rescue => e + @log.error( e.message, Log::LV_USER) + return nil + end + + FileUtils.rm_rf tmp_dir + return pkg + # if pkginfo.manifest file does not exist + else + FileUtils.rm_rf tmp_dir + return nil + end + end + + def remove_pkg( pkg_name_list, os ) + if os.eql? "all" then os_list = @support_os_list + else os_list = [ os ] + end - def remove_pkg( pkg_name_list ) - for package_name in pkg_name_list - removed_flag = false + pkg_name_list.each do |package_name| + removed_flag = false - for os in SUPPORTED_OS - if @pkg_hash_os[os].key?(package_name) then - @log.info( "remove package [#{package_name}] in #{os}", Log::LV_USER) - @pkg_hash_os[os].delete(package_name) + os_list.each do |o| + if not @support_os_list.include? o then + @log.error( "package server does not support input os : #{o}") + next + end + + if @pkg_hash_os[o].key?(package_name) then + @log.info( "remove package [#{package_name}] in #{o}", Log::LV_USER) + @pkg_hash_os[o].delete(package_name) removed_flag = true end - end + end - if not removed_flag then - @log.error( "Can't find package: #{package_name}", Log::LV_USER) + if not removed_flag then + if @archive_pkg_list.include? package_name then + @archive_pkg_list.delete package_name + else + @log.error( "Can't find package: [#{package_name}]", Log::LV_USER) + end end - end + end # check install dependency integrity - check_instll_dependency_integrity + if @integrity.eql? "YES" then + @log.info "integrity check" + check_integrity + else + @log.info "skip integrity check" + end + - for os in SUPPORTED_OS - write_pkg_list(os) + # update pkg_list file + os_list.each do |o| + write_pkg_list(o) end - end + write_archive_pkg_list + end - def check_instll_dependency_integrity - @log.info "check server pkg's install dependency integrity" + def remove_snapshot( snapshot_list ) + remain_snapshot = [] + removed_snapshot = [] - for os in SUPPORTED_OS - for pkg in @pkg_hash_os[os].each_value - error_msg = "[#{pkg.package_name}]'s install dependency not matched in " + # remove unused snapshot + Dir.new( @location + "/snapshots" ).each do |snapshot| + if snapshot.start_with? "." then next end - for dep in pkg.install_dep_list - if @pkg_hash_os[os].has_key? dep.package_name then - target_pkg = @pkg_hash_os[os][dep.package_name] - else - raise RuntimeError,(error_msg + dep.to_s) - end - - # TODO: check just install dependency exist - next - - # check package's version - if not dep.match? target_pkg.version then - raise RuntimeError,(error_msg + dep.to_s) - end - - # TODO: install dependency's os is always ture - #if not dep.target_os_list.length == 0 then - # if not dep.target_os_list.include? target_pkg.os then - # raise RuntimeError,(error_msg + dep.to_s) - # end - #end - end - - # TODO: check just install dependency - next - - error_msg = "[#{pkg.package_name}]'s build dependency not matched in " - for dep in pkg.build_dep_list - if dep.target_os_list.length == 0 then - build_dep_os = os + if snapshot_list.include? snapshot then + FileUtils.rm_rf "#{@location}/snapshots/#{snapshot}" + snapshot_list.delete snapshot + removed_snapshot.push snapshot + else + remain_snapshot.push snapshot + end + end + + if not snapshot_list.empty? then + @log.output( "snapshot not exist : #{snapshot_list.join(",")}", Log::LV_USER ) + end + + if not removed_snapshot.empty? then + @log.output( "snapshot removed: #{removed_snapshot.join(",")}", Log::LV_USER ) + end + + update_snapshot_info_file(remain_snapshot) + end + + def check_integrity + @log.info "check server pkg's install dependency integrity" + + @support_os_list.each do |os| + @pkg_hash_os[os].each_value.each do |pkg| + check_package_integrity(pkg) + end + end + end + + def check_package_integrity(pkg) + error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s install dependency not matched in " + os = pkg.os + + pkg.install_dep_list.each do |dep| + if @pkg_hash_os[os].has_key? dep.package_name then + target_pkg = @pkg_hash_os[os][dep.package_name] + else + raise RuntimeError,(error_msg + dep.to_s) + end + + # check package's version + if not dep.match? target_pkg.version then + raise RuntimeError,(error_msg + dep.to_s) + end + + end + + error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s build dependency not matched in " + pkg.build_dep_list.each do |dep| + if dep.target_os_list.length == 0 then + build_dep_os = os + else + build_dep_os = dep.target_os_list[0] + end + + if @pkg_hash_os[build_dep_os].has_key? dep.package_name then + target_pkg = @pkg_hash_os[build_dep_os][dep.package_name] + else + raise RuntimeError,(error_msg + dep.to_s) + end + + # check package's version + if not dep.match? target_pkg.version then + raise RuntimeError,(error_msg + dep.to_s) + end + end + + error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s source dependency not matched in " + pkg.source_dep_list.each do |dep| + if not @archive_pkg_list.include? dep.package_name then + raise RuntimeError,(error_msg + dep.to_s) + end + end + end + + def read_archive_pkg_list( snapshot_name ) + pkg_list = [] + + if snapshot_name.empty? + file_name = @location + "/" + ARCHIVE_PKG_FILE + else + file_name = @location + "/snapshots/" + snapshot_name + "/" + ARCHIVE_PKG_FILE + end + + if File.exist? file_name + File.open(file_name, "r") do |f| + f.each_line do |l| + pkg_list.push(l.strip) + end + end + end + + return pkg_list + end + + def write_archive_pkg_list() + File.open( "#{@location}/#{ARCHIVE_PKG_FILE}", "w" ) do |f| + @archive_pkg_list.each do |pkg| + f.puts(pkg) + end + end + end + + def initialize_pkg_list + if not File.exist? "#{@location}/#{OS_INFO_FILE}" then + return + end + + # get support_os_list + @support_os_list = [] + File.open( "#{@location}/#{OS_INFO_FILE}", "r" ) do |f| + f.each_line do |l| + @support_os_list.push l.strip + end + end + + # read package_list file + @support_os_list.each do |os| + @pkg_hash_os[os] = {} + pkg_list_file = "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" + + if File.exist? pkg_list_file then + begin + @pkg_hash_os[os] = Parser.read_repo_pkg_list_from( pkg_list_file ) + rescue => e + @log.error( e.message, Log::LV_USER) + @pkg_hash_os[os] = nil + end + end + end + + # read archive package_list file + @archive_pkg_list = read_archive_pkg_list("") + end + + def get_link_package(pkg, pkg_os) + pkg.os_list.each do |os| + # skip in same os for origin package + if pkg_os.eql? os then next end + # skip in unsupported os + if not @support_os_list.include? os then next end + + exist_pkg = @pkg_hash_os[os][pkg.package_name] + if exist_pkg.nil? then next end + + compare_version = Utils.compare_version(pkg.version, exist_pkg.version) + # if version same then compatible package + if compare_version == 0 then + return exist_pkg + end + end + + return nil + end + + # PRIVATE METHODS/VARIABLES + private + + def sync_package( pkg_name, client, os, force ) + server_pkg = client.pkg_hash_os[os][pkg_name] + local_pkg = @pkg_hash_os[os][pkg_name] + + # if server and local has package + if ( not server_pkg.nil? ) and ( not local_pkg.nil? ) then + version_cmp = Utils.compare_version( local_pkg.version, server_pkg.version ) + if ( version_cmp == 0 ) then + # version is same then skip update + return nil + end + + if ( version_cmp == -1 ) then + # local package's version is higher than server packages's version then skip update + return nil + end + + if ( local_pkg.origin.eql? "local" ) and (not force) then + # local_pkg is generated from local and not force mode then skip update + return nil + end + + pkg = sync_package2( server_pkg, client, os ) + return ["ADD", os, pkg] + # if package exist only server + elsif ( not server_pkg.nil? ) then + pkg = sync_package2( server_pkg, client, os ) + return ["ADD", os, pkg] + # if package exist only local + elsif ( not local_pkg.nil? ) then + # if local pkg is generated from local then skip + if local_pkg.origin.eql? "local" and (not force) then + return nil + end + + # package remove + return ["REMOVE", os, local_pkg] + else + raise RuntimeError,"hash merge error!" + end + + return nil + end + + def sync_package2( pkg, client, os ) + pkg_name = pkg.package_name + + # package update + file_path_list = client.download( pkg_name, os, false ) + + # file download error check + if file_path_list.nil? or file_path_list.empty? then + @log.error("Can't download package file [#{pkg_name}]", Log::LV_USER) + return nil + else + file_path = file_path_list[0] + end + + # update pkg class + pkg.path = "/binary/#{File.basename(file_path)}" + pkg.origin = client.server_addr + return pkg + + end + + def update_snapshot_info_file(remain_snapshot_list) + if not File.exist? "#{@location}/#{SNAPSHOT_INFO_FILE}" + @log.error "Can not find snapshot info file" + return + end + + # generate temp file + tmp_file_name = "" + while ( tmp_file_name.empty? ) + tmp_file_name = @location + "/temp/." + Utils.create_uniq_name + + if File.exist? tmp_file_name then + tmp_file_name = "" + end + end + + # modify snapshot info File + info_file = File.readlines("#{@location}/#{SNAPSHOT_INFO_FILE}") + File.open(tmp_file_name, 'w') do |f| + save_flag = false + info_file.each do |line| + if line =~ /name :/ then + if remain_snapshot_list.include? line.split(':')[1].strip then + save_flag = true else - build_dep_os = dep.target_os_list[0] + save_flag = false end - if @pkg_hash_os[build_dep_os].has_key? dep.package_name then - target_pkg = @pkg_hash_os[build_dep_os][dep.package_name] - else - raise RuntimeError,(error_msg + dep.to_s) - end - - # check package's version - if not dep.match? target_pkg.version then - raise RuntimeError,(error_msg + dep.to_s) - end - - # TODO: check package's target_os - #if not dep.target_os_list.length == 0 then - # if not dep.target_os_list.include? target_pkg.os then - # raise RuntimeError,(error_msg + dep.to_s) - # end - #end - end - - error_msg = "[#{pkg.package_name}]'s source dependency not matched in " - for dep in pkg.source_dep_list - # check source package exist - if not File.exist? "#{@location}/source/#{dep.package_name}" - raise RuntimeError,(error_msg + dep.to_s) - end - end - end - end + end + + if save_flag then + f.puts line + end + end + end + + FileUtils.mv( tmp_file_name, "#{@location}/#{SNAPSHOT_INFO_FILE}", :force => true ) + end + + def get_all_reverse_depends_pkgs(pkg, checked_list) + depends_list = [] + + @support_os_list.each do |os| + @pkg_hash_os[os].each_value do |dpkg| + if dpkg.install_dep_list.include? pkg or \ + dpkg.build_dep_list.include? pkg then + depends_list.push opkg + end + + end + end + + depends_list.each do |dpkg| + checked_list.push dpkg + rdepends_list = get_all_reverse_depends_pkgs( dpkg, checked_list ) + end + + return rdepends_list + end + + def reload_distribution_information + if not File.exist?("#{@location}/#{OS_INFO_FILE}") then + return + end + + # get support_os_list + @support_os_list = [] + File.open( "#{@location}/#{OS_INFO_FILE}", "r" ) do |f| + f.each_line do |l| + @support_os_list.push l.strip + end + end + + # read binary package_list file + @support_os_list.each do |os| + @pkg_hash_os[os] = {} + pkg_list_file = "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" + + if File.exist? pkg_list_file then + begin + @pkg_hash_os[os] = Parser.read_repo_pkg_list_from( pkg_list_file ) + rescue => e + @log.error( e.message, Log::LV_USER) + @pkg_hash_os[os] = nil + end + end + end + + # read archive package_list file + @archive_pkg_list = read_archive_pkg_list( "" ) + end + + def remove_os(os) + if not @support_os_list.include? os then + @log.error("Can't remove os : #{os} does not exist ", Log::LV_USER) + end + + # update os information + @support_os_list.delete os + @pkg_hash_os.delete os + + # generate temp file + tmp_file_name = "" + while ( tmp_file_name.empty? ) + tmp_file_name = @location + "/temp/." + Utils.create_uniq_name + + if File.exist? tmp_file_name then + tmp_file_name = "" + end + end + + info_file = File.readlines("#{@location}/#{OS_INFO_FILE}") + File.open(tmp_file_name, "w") do |f| + info_file.each do |line| + if not line.strip.eql? os then + f.puts line + end + end + end + + FileUtils.mv( tmp_file_name, "#{@location}/#{OS_INFO_FILE}", :force => true ) + + # delete pkg_list_#{os} file + File.delete( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" ) + end + + def sync_archive_pkg + client = Client.new( @server_url, "#{@location}/source", @log ) + + download_list = client.archive_pkg_list - @archive_pkg_list + + updated_file_list = [] + + # if update list is empty then return empty array + if download_list.empty? then return updated_file_list end + + download_list.each do |pkg| + file = client.download_dep_source(pkg) + if file.nil? + @log.error("Can't download archive package [#{pkg}]", Log::LV_USER) + else + updated_file_list.push pkg + end + end + + return updated_file_list end + end diff --git a/src/pkg_server/downloader.rb b/src/pkg_server/downloader.rb index 0308208..b5dd1ec 100644 --- a/src/pkg_server/downloader.rb +++ b/src/pkg_server/downloader.rb @@ -1,6 +1,6 @@ =begin - - downloader.rb + + downloader.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -31,38 +31,40 @@ require "utils" class FileDownLoader - @@log = nil - - def FileDownLoader.set_logger(logger) - @@log = logger - end - - def FileDownLoader.download(url, path) - ret = false - - if not File.directory? path then - @@log.error "\"#{path}\" does not exist" - return ret - end - - is_remote = Utils.is_url_remote(url) - filename = url.split('/')[-1] - - fullpath = File.join(path, filename) - - if is_remote then - ret = system "wget #{url} -O #{fullpath} -nv" - else - if not File.exist? url then - @@log.error "\"#{url}\" file does not exist" - return false - else - ret = system "cp #{url} #{fullpath}" - end - end - - # need verify - return ret - end + def FileDownLoader.download(url, path, logger) + ret = false + + if not File.directory? path then + logger.error "\"#{path}\" does not exist" + return ret + end + + is_remote = Utils.is_url_remote(url) + filename = url.split('/')[-1] + fullpath = File.join(path, filename) + + logger.info "Downloading #{url}" + if is_remote then + pid,status = Utils.execute_shell_with_log( "wget #{url} -O #{fullpath} -nv --tries=3", logger.path ) + ret = (not status.nil? and status.exitstatus != 0) ? false : true + #ret = Utils.execute_shell( "wget #{url} -O #{fullpath} -q") + else + if not File.exist? url then + logger.error "\"#{url}\" file does not exist" + return false + else + ret = system "cp #{url} #{fullpath}" + end + end + + # need verify + if ret then + logger.info "Downloaded #{filename}.. OK" + else + logger.info "Failed to download #{filename}" + logger.info " [dist: #{path}]" + end + return ret + end end diff --git a/src/pkg_server/installer.rb b/src/pkg_server/installer.rb index 0006b8d..58febe9 100644 --- a/src/pkg_server/installer.rb +++ b/src/pkg_server/installer.rb @@ -1,6 +1,6 @@ =begin - - installer.rb + + installer.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -28,273 +28,462 @@ Contributors: $LOAD_PATH.unshift File.dirname(__FILE__) $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" -require "serverConfig" +require "packageServerConfig" require "log" require "utils" +if Utils.is_windows_like_os( Utils::HOST_OS ) then + require "rubygems" + require "zip/zip" +end class FileInstaller - CONFIG_PATH = "#{$build_tools}/client" - PACKAGE_INFO_DIR = ".info" - - @@log = nil - - def FileInstaller.set_logger(logger) - @@log = logger - end - - def FileInstaller.install(package_name, package_file_path, type, target_path) - - if not File.exist? package_file_path then - @@log.error "\"#{package_file_path}\" file does not exist." - return false - end - - case type - # install script when binary package - when "binary" then - uniq_name = Utils.create_uniq_name - path = Utils::HOME + "/tmp/#{uniq_name}" - if Utils::HOST_OS.eql? "windows" then - drive = Utils::HOME.split("/")[0] - path = "#{drive}/#{uniq_name}" - end - FileUtils.mkdir_p "#{path}" - - if File.directory? path then - log = "##### create temporary dir : #{path} #####\n" - else - log = "##### [Failed] create temporary dir : #{path} #####\n" - return false - end - - log = log + "##### extract file : #{package_file_path} #####\n" - log = log + extract_file(package_name, package_file_path, path, target_path) - move_dir(package_name, path, target_path) - - log = log + "##### execute install script #####\n" - log = log + execute_install_script(package_name, path, target_path) - - log = log + "##### move remove script #####\n" - move_remove_script(package_name, path, target_path) - - log = log + "##### remove temporary dir : #{path} #####\n" - Utils.execute_shell("rm -rf #{path}") - - target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" - FileUtils.mkdir_p(target_config_path) - pkg_inst_log = "#{package_name}_inst.log" - pkg_inst_log_path = File.join(target_config_path, pkg_inst_log) - - File.open(pkg_inst_log_path, "a+") do |f| - f.puts log - end - - when "source" then - end - - # need verify - return true; - end - - def FileInstaller.move_remove_script(package_name, path, target_path) - target_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" - FileUtils.mkdir_p(target_path) - script_file_prefix = "#{path}/remove.*" - script_file = Dir.glob(script_file_prefix)[0] - - if not script_file.nil? then - FileUtils.mv(script_file, target_path) - end - end - - - def FileInstaller.execute_install_script(package_name, path, target_path) - script_file_prefix = "#{path}/install.*" - script_file = Dir.glob(script_file_prefix)[0] - log = "" - - if not script_file.nil? then - @@log.info "Execute \"#{script_file}\" file" - cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}" - log = `#{cmd}` - end - return log - end - - def FileInstaller.execute_remove_script(package_name, target_path) - info_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" - if not File.directory? info_path then - return false - end - - script_file_prefix = "#{info_path}/remove.*" - script_file = Dir.glob(script_file_prefix)[0] - log = "" - - if not script_file.nil? then - @@log.info "Execute \"#{script_file}\" file" - cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}" - log = `#{cmd}` - end - end - - def FileInstaller.remove_pkg_files(package_name, target_path) - list_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" - - if not File.directory? list_path then - return false - end - - list_file_name = "#{list_path}/#{package_name}.list" - list_file = Dir.glob(list_file_name)[0] - directories = [] - - if not list_file.nil? then - File.open(list_file, "r") do |file| - file.each_line do |f| - f = f.strip - if f.nil? or f.empty? then next end - file_path = File.join(target_path, f) - if File.directory? file_path then - if File.symlink? file_path then - File.unlink file_path - next - end - entries = Dir.entries(file_path) - if entries.include? "." then entries.delete(".") end - if entries.include? ".." then entries.delete("..") end - if entries.empty? or entries.nil? then - begin - Dir.rmdir(file_path) - rescue SystemCallError - @@log.warn "\"#{file_path}\" directory is not empty" - end - else directories.push(file_path) end - elsif File.file? file_path then FileUtils.rm_f(file_path) - elsif File.symlink? file_path then File.unlink file_path - # if files are already removed by remove script, - else @@log.warn "\"#{file_path}\" does not exist" end - end - end - - directories.reverse.each do |path| - entries = Dir.entries(path) - if entries.include? "." then entries.delete(".") end - if entries.include? ".." then entries.delete("..") end - if entries.empty? or entries.nil? then - begin - Dir.rmdir(path) - rescue SystemCallError - @@log.warn "\"#{file_path}\" directory is not empty" - end - else next end - end - end - #FileUtils.rm_rf(list_path) - Utils.execute_shell("rm -rf #{list_path}") - return true - end - - def FileInstaller.uninstall(package_name, type, target_path) - case type - when "binary" then - execute_remove_script(package_name, target_path) - remove_pkg_files(package_name, target_path) - when "source" then - end - - return true - end - - def FileInstaller.move_dir(package_name, source_path, target_path) - config_path = File.join(target_path, PACKAGE_INFO_DIR, package_name) - FileUtils.cp_r Dir.glob("#{source_path}/data/*"), target_path - FileUtils.cp "#{source_path}/pkginfo.manifest", config_path - end - - def FileInstaller.extract_file(package_name, package_file_path, path, target_path) - dirname = File.dirname(package_file_path) - filename = File.basename(package_file_path) - ext = File.extname(filename) - - target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" - FileUtils.mkdir_p(target_config_path) - pkg_file_list = "#{package_name}.list" - pkg_file_list_path = File.join(target_config_path, pkg_file_list) - temp_pkg_file_list = "temp_file_list" - temp_pkg_file_list_path = File.join(target_config_path, "temp_file_list") - - show_file_list_command = nil - extrach_file_list_command = nil - - case ext - when ".zip" then - show_file_list_command = "zip -sf #{package_file_path}" - extract_file_list_command = "unzip \"#{package_file_path}\" -d \"#{path}\"" - when ".tar" then - show_file_list_command = "tar -sf #{package_file_path}" - extract_file_list_command = "tar xf \"#{package_file_path}\" -C \"#{path}\"" - else - @@log.error "\"#{filename}\" is not supported." - return nil - end - - system "#{show_file_list_command} > #{temp_pkg_file_list_path}" - File.open(pkg_file_list_path, "a+") do |targetfile| - File.open(temp_pkg_file_list_path, "r") do |sourcefile| - sourcefile.each_line do |l| - if l.strip.start_with? "data/" then - ml = l.strip[5..-1] - targetfile.puts ml - else next end - end - end - end - - File.delete(temp_pkg_file_list_path) - log = `#{extract_file_list_command}` - @@log.info "Extracted \"#{filename}\" file.." - if log.nil? then log = "" end - return log - end - - def FileInstaller.extract_specified_file(package_file_path, target_file, path) - dirname = File.dirname(package_file_path) - filename = File.basename(package_file_path) - ext = File.extname(filename) - - case ext - when ".zip" then - if not path.nil? then - extract_file_command = "unzip -x #{package_file_path} #{target_file} -d #{path}" - else - extract_file_command = "unzip -x #{package_file_path} #{target_file}" - end - when ".tar" then - if not path.nil? then - path = File.join(path, package_file_path) - extract_file_command = "tar xvf #{package_file_path} #{target_file}" - else - extract_file_command = "tar xvf #{package_file_path} #{target_file}" - end - end - - system "#{extract_file_command}" - - if not path.nil? then - target_file_path = File.join(path, target_file) - else - target_file_path = target_file - end - - if File.exist? target_file_path then - @@log.info "Extracted \"#{target_file}\" file.." - return true - else - @@log.info "Failed to extracted \"#{target_file}\" file.." - return false - end - end + CONFIG_PATH = "#{PackageServerConfig::CONFIG_ROOT}/client" + PACKAGE_INFO_DIR = ".info" + PACKAGE_MANIFEST = "pkginfo.manifest" + + def FileInstaller.install(package_name, package_file_path, type, target_path, logger) + + if not File.exist? package_file_path then + logger.error "\"#{package_file_path}\" file does not exist." + return false + end + + case type + # install script when binary package + when "binary" then + uniq_name = Utils.create_uniq_name + path = Utils::HOME + "/tmp/#{uniq_name}" + # windows has limitation for file path length + if Utils.is_windows_like_os( Utils::HOST_OS ) then + drive = Utils::HOME.split("/")[0] + path = "#{drive}/#{uniq_name}" + end + if not File.exist? path then FileUtils.mkdir_p "#{path}" end + + if File.directory? path then + log = "## create temporary dir : #{path}\n" + else + logger.error "Failed to create temporary dir" + logger.info " [path: #{path}]" + return false + end + + begin + logger.info "Installing \"#{package_name}\" package.." + logger.info " [file: #{package_file_path}]" + + log = log + "## Extract file : #{package_file_path}\n" + result = extract_file(package_name, package_file_path, path, target_path, logger) + if result == "" or result.nil? then + write_log(target_path, package_name, log) + return false + else log = log + result end + + log = log + "## Move files : \"#{path}\" to \"#{target_path}\"\n" + result = move_dir(package_name, path, target_path, logger) + if result.nil? then + write_log(target_path, package_name, log) + return false + else log = log + result end + + log = log + "## Execute install script\n" + result = execute_install_script(package_name, path, target_path, logger) + if result.nil? then + write_log(target_path, package_name, log) + return false + else log = log + result end + + log = log + "## Move remove script\n" + result = move_remove_script(package_name, path, target_path, logger) + if result.nil? then + write_log(target_path, package_name, log) + return false + else log = log + result end + + log = log + "## Remove temporary dir : #{path} #####\n" + result = Utils.execute_shell_return("rm -rf #{path}") + if result.nil? then + logger.warn "Failed to remove temporary path" + logger.info " [path: #{path}]" + end + rescue Interrupt + logger.error "FileInstaller: Interrupted.." + Utils.execute_shell("rm -rf #{path}") + logger.info "Removed #{path}" + raise Interrupt + end + write_log(target_path, package_name, log) +=begin + target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" + if not File.exist? target_config_path then FileUtils.mkdir_p(target_config_path) end + pkg_inst_log = "#{package_name}_inst.log" + pkg_inst_log_path = File.join(target_config_path, pkg_inst_log) + + File.open(pkg_inst_log_path, "a+") do |f| + f.puts log + end +=end + when "source" then + end + + # need verify + logger.info "Installed \"#{package_name}\" package.. OK" + logger.info " [path: #{target_path}]" + return true; + end + + def FileInstaller.write_log(target_path, package_name, log) + target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" + if not File.exist? target_config_path then FileUtils.mkdir_p(target_config_path) end + pkg_inst_log = "#{package_name}_inst.log" + pkg_inst_log_path = File.join(target_config_path, pkg_inst_log) + + File.open(pkg_inst_log_path, "a+") do |f| + f.puts log + end + end + + def FileInstaller.move_remove_script(package_name, path, target_path, logger) + target_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" + if not File.exist? target_path then FileUtils.mkdir_p(target_path) end + script_file_prefix = "#{path}/remove.*" + script_file = Dir.glob(script_file_prefix)[0] + log = "" + + if not script_file.nil? then + result = Utils.execute_shell_return("mv #{script_file} #{target_path}") + if result.nil? then + logger.error "Failed to move a remove script" + logger.info " [file: #{script_file}]" + logger.info " [from: #{path}]" + logger.info " [to: #{target_path}]" + return nil + else log = result.join("") end + logger.info "Moved remove script file.. OK" + log = log + "[file: #{script_file}]\n" + log = log + "[from: #{path}]\n" + log = log + "[to: #{target_path}]\n" + end + + return log + end + + + # Does not verify that the script execution is successful. + # Register shortcut should be failed. + def FileInstaller.execute_install_script(package_name, path, target_path, logger) + script_file_prefix = "#{path}/install.*" + script_file = Dir.glob(script_file_prefix)[0] + log = "" + + if not script_file.nil? then + logger.info "Execute \"#{script_file}\" file" + if Utils.is_windows_like_os( Utils::HOST_OS ) then + target_path = target_path.gsub("/","\\") + cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}" + else + `chmod +x #{script_file}` + cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}" + end + logger.info " [cmd: #{cmd}]" + log = `#{cmd}` + logger.info "Executed install script file.. OK" + log = log + "[file: #{script_file}]\n" + log = log + "[cmd: #{cmd}]\n" + end + + return log + end + + # Does not verify that the script execution is successful. + # Removing shortcut should be failed. + def FileInstaller.execute_remove_script(package_name, target_path, logger) + info_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" + if not File.directory? info_path then + logger.error "\"#{info_path}\" does not exist." + return nil + end + + script_file_prefix = "#{info_path}/remove.*" + script_file = Dir.glob(script_file_prefix)[0] + log = "" + + if not script_file.nil? then + logger.info "Execute \"#{script_file}\" file" + if Utils.is_windows_like_os( Utils::HOST_OS ) then + target_path = target_path.gsub("/","\\") + cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}" + else + `chmod +x #{script_file}` + cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}" + end + logger.info " [cmd: #{cmd}]" + log = `#{cmd}` + logger.info "Executed remote script file.. OK" + log = log + "[file: #{script_file}]\n" + log = log + "[cmd: #{cmd}]\n" + end + + return log + end + + def FileInstaller.remove_pkg_files(package_name, target_path, logger) + list_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" + + if not File.directory? list_path then + logger.error "\"#{list_path}\" does not exist." + return false + end + + list_file_name = "#{list_path}/#{package_name}.list" + list_file = Dir.glob(list_file_name)[0] + directories = [] + + if not list_file.nil? then + File.open(list_file, "r") do |file| + file.each_line do |f| + f = f.strip + if f.nil? or f.empty? then next end + file_path = File.join(target_path, f) + if File.directory? file_path then + if File.symlink? file_path then + File.unlink file_path + next + end + entries = Dir.entries(file_path) + if entries.include? "." then entries.delete(".") end + if entries.include? ".." then entries.delete("..") end + if entries.empty? or entries.nil? then + begin + Dir.rmdir(file_path) + rescue SystemCallError + logger.warn "\"#{file_path}\" directory is not empty" + end + else directories.push(file_path) end + elsif File.file? file_path then FileUtils.rm_f(file_path) + elsif File.symlink? file_path then File.unlink file_path + # if files are already removed by remove script, + else logger.warn "\"#{file_path}\" does not exist" end + end + end + + directories.reverse.each do |path| + if not File.directory? path then next end + entries = Dir.entries(path) + if entries.include? "." then entries.delete(".") end + if entries.include? ".." then entries.delete("..") end + if entries.empty? or entries.nil? then + begin + Dir.rmdir(path) + rescue SystemCallError + logger.warn "\"#{file_path}\" directory is not empty" + end + else next end + end + end + Utils.execute_shell("rm -rf #{list_path}") + return true + end + + def FileInstaller.uninstall(package_name, type, target_path, logger) + case type + when "binary" then + result = execute_remove_script(package_name, target_path, logger) + if result.nil? then return false end + if not remove_pkg_files(package_name, target_path, logger) then return false end + when "source" then + end + + return true + end + + def FileInstaller.move_dir(package_name, source_path, target_path, logger) + config_path = File.join(target_path, PACKAGE_INFO_DIR, package_name) + pkginfo_path = File.join(source_path, PACKAGE_MANIFEST) + data_path = File.join(source_path, "data") + log = "" + + if not File.exist? pkginfo_path then + logger.error "#{PACKAGE_MANIFEST} file does not exist. Check #{source_path}" + return nil + else FileUtils.cp pkginfo_path, config_path end + + if File.exist? data_path then + if Dir.entries(data_path).count > 2 then + # if os is linux, use cpio. it is faster than cp + if Utils.is_linux_like_os( Utils::HOST_OS ) then + absolute_path = `readlink -f #{target_path}` + result = Utils.execute_shell_return("cd #{data_path}; find . -depth | cpio -pldm #{absolute_path}") + else + result = Utils.execute_shell_return("cp -r #{data_path}/* #{target_path}") + end + if result.nil? then + logger.error "Failed to move files" + logger.info " [from: #{source_path}]" + logger.info " [to: #{target_path}]" + return nil + end + logger.info "Moved files.. OK" + log = log + "[from: #{source_path}]\n" + log = log + "[to: #{target_path}]\n" + end + else logger.warn "\"data\" directory does not exist." end + + return log + end + + def FileInstaller.extract_file(package_name, package_file_path, path, target_path, logger) + dirname = File.dirname(package_file_path) + filename = File.basename(package_file_path) + ext = File.extname(filename) + + target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}" + if not File.exist? target_config_path then FileUtils.mkdir_p(target_config_path) end + pkg_file_list = "#{package_name}.list" + pkg_file_list_path = File.join(target_config_path, pkg_file_list) + temp_pkg_file_list = "temp_file_list" + temp_pkg_file_list_path = File.join(target_config_path, "temp_file_list") + + show_file_list_command = nil + extrach_file_list_command = nil + log = "" + + case ext + when ".zip" then + show_file_list_command = "zip -sf #{package_file_path}" + extract_file_list_command = "unzip -o \"#{package_file_path}\" -d \"#{path}\"" + when ".tar" then + # path should be unix path if it is used in tar command + _package_file_path = Utils.get_unix_path(package_file_path) + _path = Utils.get_unix_path(path) + show_file_list_command = "tar -tf #{_package_file_path}" + extract_file_list_command = "tar xf \"#{_package_file_path}\" -C \"#{_path}\"" + else + logger.error "\"#{filename}\" is not supported." + return nil + end + + system "#{show_file_list_command} > #{temp_pkg_file_list_path}" + File.open(pkg_file_list_path, "a+") do |targetfile| + File.open(temp_pkg_file_list_path, "r") do |sourcefile| + sourcefile.each_line do |l| + if l.strip.start_with? "data/" then + ml = l.strip[5..-1] + targetfile.puts ml + else next end + end + end + end + File.delete(temp_pkg_file_list_path) + + case ext + when ".zip" then + if Utils.is_windows_like_os( Utils::HOST_OS ) then + log = unzip_file(package_file_path, path) + else + #result = Utils.execute_shell_return(extract_file_list_command) + #if result.nil? then log = nil + #else log = result.join("") end + log = `#{extract_file_list_command}` + end + when ".tar" then + #result = Utils.execute_shell_return(extract_file_list_command) + #if result.nil? then log = nil + #else log = result.join("") end + log = `#{extract_file_list_command}` + end + + if log == "" then log = nil end + if log.nil? then + logger.error "Failed to extract \"#{filename}\" file" + logger.info " [file: #{package_file_path}]" + logger.info " [from: #{path}]" + logger.info " [to: #{target_path}]" + logger.info " [cmd: #{extract_file_list_command}]" + return nil + end + + logger.info "Extracted \"#{filename}\" file.. OK" + log = log + "[file: #{package_file_path}]\n" + log = log + "[from: #{path}]\n" + log = log + "[to: #{target_path}]\n" + log = log + "[cmd: #{extract_file_list_command}]\n" + return log + end + + def FileInstaller.extract_a_file(package_file_path, target_file, path, logger) + dirname = File.dirname(package_file_path) + filename = File.basename(package_file_path) + ext = File.extname(filename) + + case ext + when ".zip" then + if not path.nil? then + extract_file_command = "unzip -x #{package_file_path} #{target_file} -d #{path}" + else + extract_file_command = "unzip -x #{package_file_path} #{target_file}" + end + when ".tar" then + # path should be unix path if it is used in tar command + _package_file_path = Utils.get_unix_path(package_file_path) + _path = Utils.get_unix_path(path) + if not path.nil? then + extract_file_command = "tar xf #{_package_file_path} -C #{_path} #{target_file}" + else + extract_file_command = "tar xf #{_package_file_path} #{target_file}" + end + end + + system "#{extract_file_command}" + + if not path.nil? then + target_file_path = File.join(path, target_file) + else + target_file_path = target_file + end + + if File.exist? target_file_path then + logger.info "Extracted \"#{target_file}\" file.." + return true + else + logger.warn "Failed to extracted \"#{target_file}\" file.." + logger.info " [file: #{package_file_path}]" + logger.info " [path: #{path}]" + logger.info " [cmd: #{extract_file_command}]" + return false + end + end + + def FileInstaller.unzip_file(zipfile, dest) + log = "" + Zip::ZipFile.open(zipfile) do |zip_file| + zip_file.each do |f| + f_path = File.join(dest, f.name) + FileUtils.mkdir_p(File.dirname(f_path)) + if File.exist?(f_path) then + log = log + "[Warn] Exist file : #{f_path}\n" unless f_path.end_with? "/" + else + zip_file.extract(f, f_path) + if not f_path.end_with? "/" then + log = log + "[info] Extracted file : #{f_path}\n" + end + end + end + end + return log + end + + def FileInstaller.unzip_a_file(zipfile, file, dest) + Zip::ZipFile.open(zipfile) do |zip_file| + zip_file.each do |f| + if f.name.strip == file then + f_path = File.join(dest, f.name) + FileUtils.mkdir_p(File.dirname(f_path)) + zip_file.extract(f, f_path) unless File.exist?(f_path) + break + end + end + end + end end - diff --git a/src/pkg_server/packageServer.rb b/src/pkg_server/packageServer.rb index dce1b6b..e490275 100644 --- a/src/pkg_server/packageServer.rb +++ b/src/pkg_server/packageServer.rb @@ -1,6 +1,6 @@ =begin - - packageServer.rb + + packageServer.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -29,329 +29,345 @@ Contributors: require 'fileutils' $LOAD_PATH.unshift File.dirname(__FILE__) $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/build_server" +require "BuildComm" require "packageServerLog" -require "serverConfig" +require "packageServerConfig" require "distribution" +require "SocketRegisterListener" require "client" require "utils" require "mail" +require "DistSync" class PackageServer - attr_accessor :id, :location - + attr_accessor :id, :location, :log, :integrity + attr_accessor :finish, :port + attr_accessor :incoming_path + attr_accessor :distribution_list + attr_accessor :sync_interval, :passwd + # constant - SUPPORTED_OS = ["linux", "windows", "darwin"] + SERVER_ROOT = "#{PackageServerConfig::CONFIG_ROOT}/pkg_server" + DIBS_LOCK_FILE_PATH = "#{SERVER_ROOT}/.server_loc" # initialize def initialize (id) - @id = id @location = "" @distribution_list = [] # distribution name -> server_url hash @dist_to_server_url = {} - - if not File.exist? $server_root then - FileUtils.mkdir_p( $server_root ) + @integrity = "YES" + @auto_sync_flag = "NO" + @finish = false + @port = 3333 + @test_time=0 #test time in mili-seconds + @lock_file= nil + @sync_interval = 3600 + @passwd = "" + + update_config_information(id) + + if not File.exist?( SERVER_ROOT ) + FileUtils.mkdir_p( SERVER_ROOT ) end - @log = PackageServerLog.new( "#{$server_root}/.#{@id}.log", $stdout) + @log = PackageServerLog.new( @log_file_path ) server_information_initialize() - set_distribution_list() end # create - def create (id, dist_name, server_url, loc = nil ) - @id = id + def create( id, dist_name, server_url, loc = nil ) + update_config_information(id) + if loc.nil? or loc.empty? then - @location = Dir.pwd + "/" + id + @location = Dir.pwd + "/" + @id else - if loc.end_with? "/" then - @location = loc + id - else - @location = loc + "/" + id + if Utils.is_absolute_path(loc) then + @location = File.join(loc, @id) + else + @location = File.expand_path(File.join(Dir.pwd, loc, @id)) end end + # error check : check for already exist in server @id + if File.exist? @config_dir + raise RuntimeError, "Server create fail. server id [#{@id}] is already exist" + end + + # name check + if dist_name.strip.eql? "distribution.info" then + raise RuntimeError, "id \"distribution.info\" is not available" + end + # create locking file - File.open("#{$server_create_loc_file}", File::RDWR|File::CREAT, 0644) {|f| - f.flock(File::LOCK_EX) - f.rewind - f.flush - f.truncate(f.pos) - - # error check : check for already exist in server id - if File.exist? "#{$server_root}/#{id}" - raise RuntimeError, "Server create fail. server id [#{id}] is already exist" - end - - # error check : check for already exist in server directory - if File.exist? "#{@location}/#{dist_name}" - raise RuntimeError, "Server create fail. directory is already exist [#{@location}/#{dist_name}]" - end - - # create server config directory - FileUtils.mkdir_p "#{$server_root}/#{id}" - FileUtils.mkdir_p "#{$server_root}/#{id}/incoming" - - if (not server_url.empty?) and (not Utils.is_url_remote(server_url)) - # if server_url is local server address then generate absoulte path - if not Utils.is_absolute_path( server_url ) then - if server_url.end_with?("/") then - server_url = Utils::WORKING_DIR + server_url - else - server_url = Utils::WORKING_DIR + "/" + server_url - end - end - end + lock_file = Utils.file_lock(DIBS_LOCK_FILE_PATH) - # create server configure file - File.open( "#{$server_root}/#{id}/config", "w" ) do |f| - f.puts "location : #{@location}" - f.puts "server_url : #{dist_name} -> #{server_url}" - end - - # create location's directory - FileUtils.mkdir_p "#{@location}" - - create_distribution_struct( dist_name, server_url ) - } + # create server config directory + FileUtils.mkdir_p @config_dir + FileUtils.mkdir_p @incoming_path + + if (not server_url.empty?) and \ + (not Utils.is_url_remote(server_url)) and \ + (not Utils.is_absolute_path(server_url)) then + # if server_url is local server address then generate absoulte path + server_url = File.join(Utils::WORKING_DIR, server_url) + end + + # create server configure file + File.open( @config_file_path, "w" ) do |f| + f.puts "location : #{@location}" + f.puts "integrity check : #{@integrity}" + f.puts "auto sync : #{@auto_sync_flag}" + f.puts "sync interval : #{@sync_interval}" + f.puts "server_url : #{dist_name} -> #{server_url}" + end + + # create location's directory + FileUtils.mkdir_p "#{@location}" + + create_distribution_struct( dist_name, server_url ) + Utils.file_unlock(lock_file) + + @log.output( "package server [#{@id}] created successfully", Log::LV_USER ) end - def register( source_pkg_file_path_list, binary_pkg_file_path_list, dist_name, snapshot, test ) + def register( file_path_list, dist_name, snapshot, test_flag, internal_flag = false ) @log.info "package register in server" - if dist_name.empty? then dist_name = get_default_dist_name() end - if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end distribution = get_distribution( dist_name ) - # distribution lock - File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f| - f.flock(File::LOCK_EX) - f.rewind - f.flush - f.truncate(f.pos) - - source_pkg_file_name_list = [] - updated_os_list = [] - append_pkg_list = [] - used_source_pkg_list = [] - package_list = [] - - # error check - source_pkg_file_path_list.each do |l| - # error check for file exist - if not File.exist? l - raise RuntimeError, "source package file does not exist [#{l}]" - end - - source_pkg_file_name_list.push File.basename( l ) - end - binary_pkg_file_path_list.each do |l| - # error check for file exist - if not File.exist? l - raise RuntimeError, "binary package file does not exist [#{l}]" - end - end - - # register binary package - binary_pkg_file_path_list.each do |l| - # get package class using bianry file - pkg = distribution.get_package_from_file(l) - - if pkg.nil? or pkg.package_name.empty? then - raise "[#{l}]'s pkginfo.manifest file is incomplete." - end - package_list.push pkg - - if test then - if not pkg.source.empty? then - if not source_pkg_file_name_list.include? "#{pkg.source}_#{pkg.version}.tar.gz" - raise "binary package and source package must be upload same time" - end - - pkg.src_path = "/temp/#{pkg.source}_#{pkg.version}.tar.gz" - end - pkg = distribution.register_for_test(l ,pkg ) + # distribution lock + @lock_file = Utils.file_lock(distribution.lock_file_path) + + updated_os_list = [] + registed_package_list = [] + binary_pkg_file_path_list = [] + link_pkg_file_path_list = [] + archive_pkg_file_path_list = [] + snapshot_name = "" + + file_path_list.each do |f| + # error check for file exist + if not File.exist? f + raise RuntimeError, "package file does not exist [#{f}]" + end + + pkg = distribution.get_package_from_file(f) + + # binary package + if not pkg.nil? then + + # find link package + pkg_os = Utils.get_os_from_package_file(f) + link_pkg = distribution.get_link_package(pkg, pkg_os) + if link_pkg.nil? then + binary_pkg_file_path_list.push f else - if pkg.package_name.empty? or pkg.version.empty? or pkg.os.empty? or pkg.maintainer.empty? then - raise "[#{l}]'s pkginfo.manifest file is incomplete." - # binary only package - elsif pkg.attribute.include? "binary" then - @log.info "binary package [#{l}] is binary only package" - pkg.src_path = "" - elsif pkg.source.empty? then - raise "[#{l}]'s pkginfo.manifest file is incomplete." - # binary package - else - if not source_pkg_file_name_list.include? "#{pkg.source}_#{pkg.version}.tar.gz" - raise "binary package [#{pkg.package_name}]'s source package must be upload same time" - end - - @log.info "binary package [#{l}]'s source package is #{pkg.source}" - used_source_pkg_list.push "#{pkg.source}_#{pkg.version}.tar.gz" - pkg.src_path = "/source/#{pkg.source}_#{pkg.version}.tar.gz" - end - - pkg = distribution.register(l ,pkg ) - updated_os_list.push pkg.os + link_pkg_file_path_list.push [link_pkg.path, File.basename(f)] + pkg.checksum = link_pkg.checksum + pkg.size = link_pkg.size end - - append_pkg_list.push pkg - end - - # check install dependency integrity - if not test then distribution.check_instll_dependency_integrity end - - source_pkg_file_path_list.each do |source_path| - source_name = File.basename(source_path) - if File.exist? "#{@location}/#{dist_name}/source/#{source_name}" then - @log.warn "source package already exist then does not register" - next - end - - if test then - @log.info "source package [#{source_name}] register in temp/]" - FileUtils.cp( source_path, "#{@location}/#{dist_name}/temp/" ) + + # update os information + if pkg.os_list.include? pkg_os then + pkg.os = pkg_os + pkg.os_list = [pkg_os] else - @log.info "source package [#{source_name}] register in source/]" - FileUtils.cp( source_path, "#{@location}/#{dist_name}/source/" ) + raise RuntimeError, "package file name is incorrect [#{f}]" end - end - # register archive pakcage list. - distribution.write_archive_pkg_list( source_pkg_file_name_list - used_source_pkg_list ) + updated_pkg = register_package(distribution, pkg, f, test_flag, internal_flag) - binary_pkg_file_path_list.each do |l| - if test then - FileUtils.cp( l, "#{@location}/#{dist_name}/temp/" ) - else - FileUtils.cp( l, "#{@location}/#{dist_name}/binary/" ) + updated_os_list.push updated_pkg.os + registed_package_list.push updated_pkg + # archive package + else + if test_flag then + @log.error("archive package does not using test mode", Log::LV_USER) + return end + + file_name = File.basename(f) + distribution.register_archive_pkg(file_name) + archive_pkg_file_path_list.push f end + end + + # check install dependency integrity + if not test_flag and @integrity.eql? "YES" then + registed_package_list.each do |pkg| + distribution.check_package_integrity(pkg) + end + end + + # move file to package server + binary_pkg_file_path_list.each do |l| + if test_flag then + FileUtils.copy_file( l, "#{distribution.location}/temp/#{File.basename(l)}" ) + else + FileUtils.copy_file( l, "#{distribution.location}/binary/#{File.basename(l)}" ) + end + end + + # link to package server + link_pkg_file_path_list.each do |l| + if test_flag then + src_file = File.join(distribution.location, l[0]) + dest_file = File.join(distribution.location, "temp", l[1]) + FileUtils.ln( src_file, dest_file, :force => true ) + else + src_file = File.join(distribution.location, l[0]) + dest_file = File.join(distribution.location, "binary", l[1]) + FileUtils.ln( src_file, dest_file, :force => true ) + end + end + + archive_pkg_file_path_list.each do |l| + FileUtils.mv( l, "#{distribution.location}/source/" ) + end - # write package list for updated os - updated_os_list.uniq! - updated_os_list.each do |os| - distribution.write_pkg_list( os ) + # write package list for updated os + updated_os_list.uniq! + updated_os_list.each do |os| + distribution.write_pkg_list(os) + end + + # register archive pakcage list. + distribution.write_archive_pkg_list() + + # send email + if test_flag then + msg_list = [] + + registed_package_list.each do |p| + msg_list.push("%-30s: %08s" % [ p.package_name.strip, p.version.strip ] ) end + # email just remote package server + # Mail.send_package_registe_mail( msg_list, @id ) + end + + # if snapshot mode is true then generate snapshot + if snapshot or test_flag then + @log.info "generaging snapshot" + snapshot_name = distribution.generate_snapshot("", "", false, "Changed package: \n" + registed_package_list.map{|x|"- #{x.package_name}"}.join("\n") + "\n\n" + get_changelog_string(registed_package_list) ) + end - # if snapshot mode is true then generate snapshot - if snapshot or test then - @log.info "generaging snapshot" - distribution.generate_snapshot("", "", "") - end - - # send email - if not test then - msg_list = [] - - package_list.map{ |p| - msg_list.push("%-30s: %08s" % [ p.package_name.strip, p.version.strip ] ) - } - # email just remote package server - # Mail.send_package_registe_mail( msg_list, @id ) + Utils.file_unlock(@lock_file) + @log.output( "package registed successfully", Log::LV_USER) + + return snapshot_name + end + + def get_changelog_string( package_list ) + log_list = {} + package_list.each do |pkg| + if not pkg.does_change_exist? then next end + set = false + if log_list[[pkg.package_name, pkg.version, pkg.get_changes]].nil? then + log_list[[pkg.package_name, pkg.version, pkg.get_changes]] = pkg.os_list + else + log_list[[pkg.package_name, pkg.version, pkg.get_changes]] = log_list[[pkg.package_name, pkg.version, pkg.get_changes]] + pkg.os_list end - } - end + end + str="" + log_list.each do |key, os_list| + str = str + "Package: #{key[0]}\nOS: #{os_list.join(", ")}\nVersion: #{key[1]}\nChanges: \n#{key[2].sub(/^==/,'Uploader:')}\n\n" + end + return str + end - def generate_snapshot( snpashot_name, dist_name, base_snapshot, binary_pkg_file_path_list) + def generate_snapshot( snpashot_name, dist_name, base_snapshot ) @log.info "generating snapshot" - if dist_name.empty? then dist_name = get_default_dist_name() end - if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end distribution = get_distribution( dist_name ) - File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f| - f.flock(File::LOCK_EX) - f.rewind - f.flush - f.truncate(f.pos) - - append_pkg_list = [] - binary_pkg_file_path_list.each do |l| - if not File.exist? l then raise RuntimeError,"Can't find binary package file [#{l}]" end - pkg = distribution.get_package_from_file(l) - if l.start_with? "/" - pkg.path = "#{l}" - else - pkg.path = "#{Dir.pwd}/#{l}" - end - append_pkg_list.push pkg - end - - distribution.generate_snapshot( snpashot_name, base_snapshot, append_pkg_list) - } + @lock_file = Utils.file_lock(distribution.lock_file_path) + + snapshot_name = distribution.generate_snapshot( snpashot_name, base_snapshot, true, "SYSTEM:") + + Utils.file_unlock(@lock_file) + + return snapshot_name end - def sync( dist_name, mode ) + def sync( dist_name, mode, snapshot = "" ) @log.info "sync from server" - if dist_name.empty? then dist_name = get_default_dist_name() end - if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end - distribution = get_distribution( dist_name ) - - if distribution.server_url.empty? then - @log.error( "This distribution has not remote server", Log::LV_USER) + distribution = get_distribution( dist_name ) + + if distribution.server_url.empty? then + @log.error( "This distribution has not remote server", Log::LV_USER) return - end - - File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f| - f.flock(File::LOCK_EX) - f.rewind - f.flush - f.truncate(f.pos) - - distribution.sync( mode, "linux" ) - distribution.sync( mode, "windows" ) - distribution.sync( mode, "darwin" ) - distribution.sync_archive_pkg - } + end + + begin + ret = distribution.sync(mode, snapshot) + + if ret then + distribution.generate_snapshot("", "", false, distribution.last_sync_changes) + end + + @log.output( "package server [#{@id}]'s distribution [#{dist_name}] has been synchronized.", Log::LV_USER ) + rescue => e + @log.error( e.message, Log::LV_USER) + end end def add_distribution( dist_name, server_url, clone ) - File.open("#{$server_create_loc_file}", File::RDWR|File::CREAT, 0644) {|f| - f.flock(File::LOCK_EX) - f.rewind - f.flush - f.truncate(f.pos) - - # error check : check for already exist in server directory - if @dist_to_server_url.keys.include? dist_name.strip then - raise RuntimeError, "distribution already exist : #{dist_name}" - end - if File.exist? "#{@location}/#{dist_name}" - raise RuntimeError, "distribution directory already exist [#{@location}/#{dist_name}]" - end - - if (not server_url.empty?) and (not Utils.is_url_remote(server_url)) - # if server_url is local server address then generate absoulte path - if not Utils.is_absolute_path( server_url ) then - if server_url.end_with?("/") then - server_url = Utils::WORKING_DIR + server_url - else - server_url = Utils::WORKING_DIR + "/" + server_url - end - end - end + lock_file = Utils.file_lock(@server_lock_file_path) - File.open( "#{$server_root}/#{@id}/config", "a" ) do |f| - if clone then - @log.info "add distribution using [#{server_url}] in clone mode" - f.puts "server_url : #{dist_name} -> " + # error check : check for already exist in server directory + if @dist_to_server_url.keys.include? dist_name.strip then + Utils.file_unlock(@lock_file) + raise RuntimeError, "distribution already exist : #{dist_name}" + end + + # name check + if dist_name.strip.eql? "distribution.info" then + Utils.file_unlock(@lock_file) + raise RuntimeError, "id \"distribution.info\" is not available" + end + + # modify server url + if (not server_url.empty?) and (not Utils.is_url_remote(server_url)) + # if server_url is local server address then generate absoulte path + if not Utils.is_absolute_path( server_url ) then + if server_url.end_with?("/") then + server_url = Utils::WORKING_DIR + server_url else - @log.info "add distribution using [#{server_url}]" - f.puts "server_url : #{dist_name} -> #{server_url}" + server_url = Utils::WORKING_DIR + "/" + server_url end end - - create_distribution_struct( dist_name, server_url ) - } + end + + add_dist_for_config_file(dist_name, server_url, clone) + create_distribution_struct( dist_name, server_url ) + + Utils.file_unlock(lock_file) + @log.output( "distribution [#{dist_name}] added successfully", Log::LV_USER ) end - def remove_server( id ) - @log.info( "Package server [#{id}] will be removed and all server information delete", Log::LV_USER) + def add_os(dist_name, os) + dist = get_distribution(dist_name) - if File.exist? "#{$server_root}/#{id}/config" then - File.open "#{$server_root}/#{id}/config" do |f| + # distribution lock + @lock_file = Utils.file_lock(dist.lock_file_path) + + dist.add_os(os) + + @log.info "generaging snapshot" + dist.generate_snapshot("", "", false, "Add #{os} Package server") + + Utils.file_unlock(@lock_file) + @log.output( "package server add os [#{os}] successfully", Log::LV_USER ) + end + + def remove_server() + @log.info( "Package server [#{@id}] will be removed and all server information delete", Log::LV_USER) + + lock_file = Utils.file_lock(DIBS_LOCK_FILE_PATH) + if File.exist? @config_file_path then + File.open @config_file_path do |f| f.each_line do |l| - if l.start_with?( "location : ") then + if l.start_with?( "location : ") then location= l.split(" : ")[1] FileUtils.rm_rf l.split(" : ")[1].strip @log.info( "server location removed : #{location}", Log::LV_USER) @@ -359,91 +375,245 @@ class PackageServer end end else - @log.error( "Can't find server information : #{id}", Log::LV_USER) - end - - FileUtils.rm_rf "#{$server_root}/.#{id}.log" - FileUtils.rm_rf "#{$server_root}/#{id}" + @log.error( "Can't find server information : #{@id}", Log::LV_USER) + end + + FileUtils.rm_rf @config_dir + FileUtils.rm_rf @log_file_path + + Utils.file_unlock(lock_file) + @log.output( "package server [#{@id}] removed successfully", Log::LV_USER ) end - def remove_pkg( id, dist_name, pkg_name_list ) + def remove_dist( dist_name ) + @log.info "remove distribution in server" + distribution = get_distribution( dist_name ) + + lock_file = Utils.file_lock(@server_lock_file_path) + + # modify config file + config_file = File.readlines(@config_file_path) + File.open(@config_file_path, 'w') do |f| + config_file.each do |line| + f.puts(line) if not line =~ /server_url : #{dist_name} ->/ + end + end + + # modify info file + config_file = File.readlines("#{@location}/distribution.info") + File.open("#{@location}/distribution.info", 'w') do |f| + remove_flag = false + config_file.each do |line| + if line.start_with? "name :" then + if line.split(':')[1].strip.eql? dist_name then + remove_flag = true + else + remove_flag = false + end + + end + + # rewrite information for not remove distribution + if not remove_flag then + f.puts line + end + end + end + + # remove distribution directory + FileUtils.rm_rf distribution.location + + # remove distribution struct + @distribution_list.delete distribution + + Utils.file_unlock(lock_file) + end + + def remove_pkg( dist_name, pkg_name_list, os ) @log.info "package remove in server" - if dist_name.empty? then dist_name = get_default_dist_name() end - if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end distribution = get_distribution( dist_name ) - # distribution lock - File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f| - f.flock(File::LOCK_EX) - f.rewind - f.flush - f.truncate(f.pos) + lock_file = Utils.file_lock(@server_lock_file_path) + + distribution.remove_pkg(pkg_name_list, os) - distribution.remove_pkg(pkg_name_list) - } + # generate snapshot + @log.info "generaging snapshot" + distribution.generate_snapshot("", "", false, "SYSTEM: Package \"#{pkg_name_list.join(", ")}\" is(are) removed in #{os} server") + + Utils.file_unlock(lock_file) + @log.output( "package removed successfully", Log::LV_USER ) end - def find_source_package_path( dist_name, pkg_file_name_list ) - if dist_name.empty? then dist_name = get_default_dist_name() end - if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end + def remove_snapshot( dist_name, snapshot_list ) + @log.info "remove snapshot in server" distribution = get_distribution( dist_name ) - pkg_file_name_list.each do |pkg| - pkg_path = "#{@location}/#{dist_name}/source/#{pkg}" - if File.exist? pkg_path then - @log.info( "#{pkg}", Log::LV_USER) + lock_file = Utils.file_lock(@server_lock_file_path) + + distribution.remove_snapshot(snapshot_list) + + Utils.file_unlock(lock_file) + end + + def clean( dist_name, snapshot_list ) + @log.info "pakcage server clean" + distribution = get_distribution( dist_name ) + + lock_file = Utils.file_lock(@server_lock_file_path) + + distribution.clean( snapshot_list ) + + # remove incoming dir + FileUtils.rm_rf incoming_path + FileUtils.mkdir incoming_path + + Utils.file_unlock(lock_file) + end + + # start server daemon + def start( port, passwd ) + @log.info "Package server Start..." + # set port number. default port is 3333 + @port = port + + # set job request listener + @log.info "Setting listener..." + listener = SocketRegisterListener.new(self) + listener.start + + # set auto sync + if @auto_sync_flag.eql? "YES" then + @log.info "Setting auto sync..." + autosync = DistSync.new(self) + autosync.start + end + + # set password + @passwd = passwd + + # main loop + @log.info "Entering main loop..." + if @test_time > 0 then start_time = Time.now end + while( not @finish ) + # sleep + if @test_time > 0 then + curr_time = Time.now + if (curr_time - start_time).to_i > @test_time then + puts "Test time is elapsed!" + break + end else - @log.error( "Can't find [#{pkg}] in source package", Log::LV_USER) + sleep 1 end - end + end end - def PackageServer.list_id - @@log = PackageServerLog.new( "#{$server_root}/.log", $stdout) + # stop server daemon + def stop( port, passwd ) + # set port number. default port is 3333 + @port = port + @finish = false - d = Dir.new( $server_root ) - s = d.select {|f| not f.start_with?(".") } + client = BuildCommClient.create("127.0.0.1", @port, @log) + if client.nil? then + raise RuntimeError, "Server does not listen in #{@port} port" + end + + client.send("STOP|#{passwd}") + + ret = client.receive_data + if not ret.nil? and ret[0].strip.eql? "SUCC" then + @log.output( "Package server is stopped", Log::LV_USER) + else + @log.output( "Package server return error message! #{ret}", Log::LV_USER) + if not client.get_error_msg().empty? then + @log.output( "Error: #{client.get_error_msg()}", Log::LV_USER) + end + end + client.terminate + + end + + def self.list_id + @@log = PackageServerLog.new("#{SERVER_ROOT}/.log") + + d = Dir.new( SERVER_ROOT ) + s = d.select {|f| not f.start_with?(".") } s.sort! - + server_list = [] + @@log.output( "=== server ID list ===", Log::LV_USER) s.each do |id| + if File.basename(id).include?(".log") then next end + + server_list.push id @@log.output( id, Log::LV_USER) - end + end + @@log.close + FileUtils.rm_rf("#{SERVER_ROOT}/.log") + + return server_list end - def PackageServer.list_dist( id ) - @@log = PackageServerLog.new( "#{$server_root}/.log", $stdout) - + def self.list_dist( id ) + @@log = PackageServerLog.new( "#{SERVER_ROOT}/.log" ) + @@log.output( "=== ID [#{id}]'s distribution list ===", Log::LV_USER) + dist_list = [] + # read package id information - if File.exist? "#{$server_root}/#{id}/config" then - File.open "#{$server_root}/#{id}/config" do |f| - f.each_line do |l| - if l.start_with?( "server_url : ") and l.include?( "->" ) then - @@log.output( l.split(" : ")[1].split("->")[0], Log::LV_USER) - end + config_file_path = "#{SERVER_ROOT}/#{id}/config" + if not File.exist? config_file_path + raise RuntimeError, "[#{id}] is not server ID" + end + + File.open config_file_path do |f| + f.each_line do |l| + if l.start_with?( "server_url : ") and l.include?( "->" ) then + dist_name = l.split(" : ")[1].split("->")[0] + + dist_list.push dist_name + @@log.output( dist_name, Log::LV_USER) end end - else - raise RuntimeError, "[#{id}] is not server ID" - end + end + @@log.close + FileUtils.rm_rf("#{SERVER_ROOT}/.log") + + return dist_list end - def get_default_dist_name() - if @distribution_list.empty? then + def get_default_dist_name() + if @distribution_list.empty? then raise RuntimeError,"Server [#{@id}] does not have distribution" - end - return @distribution_list[0].name + end + return @distribution_list[0].name + end + + def reload_dist_package() + # create locking file + lock_file = Utils.file_lock(@server_lock_file_path) + @distribution_list.each do |dist| + dist.initialize_pkg_list + end + Utils.file_unlock(lock_file) + end + + def release_lock_file + if not @lock_file.nil? then + Utils.file_unlock(@lock_file) + end end # PRIVATE METHODS/VARIABLES - private + private - def server_information_initialize + def server_information_initialize # if id is nil or empty then find default id - if @id.nil? or @id.empty? - d = Dir.new( $server_root ) + if @id.nil? or @id.empty? + d = Dir.new( SERVER_ROOT ) s = d.select {|f| not f.start_with?(".") } if s.length.eql? 1 then @log.info "using default server ID [#{s[0]}]" @@ -454,32 +624,43 @@ class PackageServer end # read package id information - if File.exist? $server_root and File.exist? "#{$server_root}/#{@id}/config" then - File.open "#{$server_root}/#{@id}/config" do |f| + if File.exist? @config_file_path + File.open @config_file_path do |f| f.each_line do |l| - if l.start_with?( "location : ") then - @location = l.split(" : ")[1].strip - elsif l.start_with?( "server_url : " ) then - info = l.split(" : ")[1].split("->") - @dist_to_server_url[info[0].strip] = info[1].strip + if l.start_with?( "location :") then + @location = l.split(" :")[1].strip + elsif l.start_with?( "integrity check :") then + @integrity = l.split(" :")[1].strip.upcase + elsif l.start_with?( "auto sync :" ) then + @auto_sync_flag = l.split(" :")[1].strip.upcase + elsif l.start_with?( "sync interval :" ) then + @sync_interval = l.split(" :")[1].strip.to_i + elsif l.start_with?( "server_url :" ) then + info = l.split(" :")[1].split("->") + @dist_to_server_url[info[0].strip] = info[1].strip else @log.error "server config file has invalid information [#{l}]" end end end - end - end - def set_distribution_list - @dist_to_server_url.each do |dist_name, server_url| - @distribution_list.push Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, @log) + @dist_to_server_url.each do |dist_name, server_url| + @distribution_list.push Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, self ) + end end end def get_distribution( dist_name ) + if dist_name.nil? or dist_name.empty? then + dist_name = get_default_dist_name() + end + if dist_name.empty? then + raise RuntimeError,"Can't find distribution information" + end + @distribution_list.each do |dist| if dist.name.eql? dist_name.strip - return dist + return dist end end @@ -487,40 +668,91 @@ class PackageServer end def create_distribution_struct( dist_name, server_url ) + if File.exist? "#{@location}/#{dist_name}" + raise RuntimeError, "distribution directory already exist [#{@location}/#{dist_name}]" + end + FileUtils.mkdir "#{@location}/#{dist_name}" FileUtils.mkdir "#{@location}/#{dist_name}/binary" FileUtils.mkdir "#{@location}/#{dist_name}/source" FileUtils.mkdir "#{@location}/#{dist_name}/temp" FileUtils.mkdir "#{@location}/#{dist_name}/snapshots" - + File.open("#{@location}/#{dist_name}/#{Distribution::SNAPSHOT_INFO_FILE}", "w") {} + File.open("#{@location}/#{dist_name}/#{Distribution::OS_INFO_FILE}", "w") {} + File.open("#{@location}/#{dist_name}/#{Distribution::ARCHIVE_PKG_FILE}", "w") {} + # generate distribution - distribution = Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, @log ) + distribution = Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, self ) # add dist @distribution_list.push distribution - + if not server_url.empty? then @log.info "generate package server using remote package server [#{server_url}]" - if Utils.is_url_remote(server_url) then + if Utils.is_url_remote(server_url) then @log.info "[#{dist_name}] distribution creation. using remote server [#{server_url}]" - else + else @log.info "[#{dist_name}] distribution creation. using local server [#{server_url}]" end - distribution.sync( false, "linux" ) - distribution.sync( false, "windows" ) - distribution.sync( false, "darwin" ) - distribution.sync_archive_pkg + distribution.sync(false) + distribution.generate_snapshot("", "", false, distribution.last_sync_changes) else @log.info "generate package server do not using remote package server" - + # write_pkg_list for empty file - distribution.write_pkg_list( "linux" ) - distribution.write_pkg_list( "windows" ) - distribution.write_pkg_list( "darwin" ) - distribution.write_archive_pkg_list( "" ) + distribution.write_pkg_list(nil) + distribution.write_archive_pkg_list() + end + + # add dist information to distribution.info file + File.open("#{@location}/distribution.info", "a") do |f| + f.puts "name : #{dist_name}" + f.puts "time : #{Time.now.strftime("%Y%m%d%H%M%S")}" + f.puts end end -end + def register_package(distribution, pkg, file_path, test_flag, internal_flag) + # get package class using bianry file + if pkg.nil? or pkg.package_name.empty? then + raise "[#{file_path}]'s pkginfo.manifest file is incomplete." + end + + if not test_flag then + # error check + if pkg.package_name.empty? or pkg.version.empty? \ + or pkg.os.empty? or pkg.maintainer.empty? then + raise "[#{file_path}]'s pkginfo.manifest file is incomplete." + end + + updated_pkg = distribution.register(file_path, pkg, internal_flag ) + else + updated_pkg = distribution.register_for_test(file_path, pkg ) + end + + return updated_pkg + end + + def add_dist_for_config_file(dist_name, server_url, clone) + File.open( @config_file_path, "a" ) do |f| + if clone then + @log.info "add distribution using [#{server_url}] in clone mode" + f.puts "server_url : #{dist_name} -> " + else + @log.info "add distribution using [#{server_url}]" + f.puts "server_url : #{dist_name} -> #{server_url}" + end + end + end + + def update_config_information(id) + @id = id + @config_dir = "#{SERVER_ROOT}/#{@id}" + @log_file_path = "#{SERVER_ROOT}/#{@id}.log" + @config_file_path = "#{@config_dir}/config" + @incoming_path = "#{@config_dir}/incoming" + @server_lock_file_path = "#{@config_dir}/.server_lock" + end +end diff --git a/src/pkg_server/packageServerConfig.rb b/src/pkg_server/packageServerConfig.rb new file mode 100644 index 0000000..3c782a6 --- /dev/null +++ b/src/pkg_server/packageServerConfig.rb @@ -0,0 +1,34 @@ +=begin + + serverConfig.rb + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" +require "utils" + +class PackageServerConfig + CONFIG_ROOT = "#{Utils::HOME}/.build_tools" +end diff --git a/src/pkg_server/packageServerLog.rb b/src/pkg_server/packageServerLog.rb index b20c798..1ca1068 100644 --- a/src/pkg_server/packageServerLog.rb +++ b/src/pkg_server/packageServerLog.rb @@ -1,6 +1,6 @@ =begin - - packageServerLog.rb + + packageServerLog.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -32,15 +32,15 @@ require "logger" class PackageServerLog < Log - def initialize(path, stream_out) + def initialize(path) super(path) - @extra_out = stream_out + @second_out = $stdout end protected def output_extra(msg) - @extra_out.puts msg - end + @second_out.puts msg + end end diff --git a/src/pkg_server/serverOptParser.rb b/src/pkg_server/serverOptParser.rb index bdacd82..f37d68b 100644 --- a/src/pkg_server/serverOptParser.rb +++ b/src/pkg_server/serverOptParser.rb @@ -1,6 +1,6 @@ =begin - - serverOptParser.rb + + serverOptParser.rb Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. @@ -30,171 +30,224 @@ require 'optparse' $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" require "utils" -def set_default( options ) - if options[:id].nil? then options[:id] = "" end - if options[:dist].nil? then options[:dist] = "" end - if options[:url].nil? then options[:url] = "" end - if options[:os].nil? then options[:os] = "all" end - if options[:bpkgs].nil? then options[:bpkgs] = [] end - if options[:apkgs].nil? then options[:apkgs] = [] end - if options[:spkgs].nil? then options[:spkgs] = [] end - if options[:snap].nil? then options[:snap] = "" end - if options[:bsnap].nil? then options[:bsnap] = "" end - if options[:gensnap].nil? then options[:gensnap] = false end - if options[:force].nil? then options[:force] = false end - if options[:test].nil? then options[:test] = false end - if options[:clone].nil? then options[:clone] = false end +def set_default( options ) + options[:id] = "" + options[:dist] = "" + options[:url] = "" + options[:os] = "all" + options[:pkgs] = [] + options[:snaps] = [] + options[:bsnap] = "" + options[:port] = "3333" + options[:gensnap] = true + options[:force] = false + options[:test] = false + options[:clone] = false + options[:origin_pkg_name] = "" + options[:origin_pkg_os] = "" + options[:passwd] = "" end def option_error_check( options ) - - case options[:cmd] - when "create" - if options[:id].empty? or options[:dist].empty? then - raise ArgumentError, "Usage: pkg-svr create -i -d [-u ] [-l ] " - end - when "remove-pkg" - if options[:bpkgs].empty? then - raise ArgumentError, "pkg-svr remove-pkg -i -d -p " + "\n" \ - end - when "spkg-path" - if options[:spkgs].empty? then - raise ArgumentError, "Usage: pkg-svr spkg-name -i -d -s " + + case options[:cmd] + when "create" + if options[:id].empty? or options[:dist].empty? then + raise ArgumentError, "Usage: pkg-svr create -n -d [-u ] [-l ] " end when "remove" if options[:id].empty? then - raise ArgumentError, "Usage: pkg-svr remove -i " + raise ArgumentError, "Usage: pkg-svr remove -n " + end + when "remove-pkg" + if options[:pkgs].empty? then + raise ArgumentError, "Usage: pkg-svr remove-pkg -n -d -P [-o ]" + "\n" \ + end + when "remove-snapshot" + if options[:snaps].empty? then + raise ArgumentError, "Usage: pkg-svr remove-snapshot -n -d -s " end when "add-dist" - if options[:id].empty? or options[:dist].empty? then - raise ArgumentError, "Usage: pkg-svr add-dist -i -d [-u ] [-c] " + if options[:id].empty? or options[:dist].empty? then + raise ArgumentError, "Usage: pkg-svr add-dist -n -d [-u ] [--clone] " + end + when "add-os" + if options[:os].empty? then + raise ArgumentError, "Usage: pkg-svr add-os -n -d -o ] " + end + when "remove-dist" + if options[:id].empty? or options[:dist].empty? then + raise ArgumentError, "Usage: pkg-svr remove-dist -n -d " end when "register" - if options[:bpkgs].empty? and options[:spkgs].empty? then - raise ArgumentError, "Usage: pkg-svr register -i -d -p -s [-g] [-t] " + if options[:pkgs].empty? then + raise ArgumentError, "Usage: pkg-svr register -n -d -P [--gen] [--test] " end - when "remove" when "gen-snapshot" + if options[:snaps].empty? then + raise ArgumentError, "Usage: pkg-svr gen-snapshot -n -d -s [-b ]" + end + when "start" + if options[:port].empty? then + raise ArgumentError, "Usage: pkg-svr start -n -p [-w ]" + end + when "stop" + if options[:port].empty? then + raise ArgumentError, "Usage: pkg-svr stop -n -p [-w ]" + end when "sync" when "list" + when "clean" else - raise ArgumentError, "input option incorrect : #{options[:cmd]}" + raise ArgumentError, "Input is incorrect : #{options[:cmd]}" end end -def option_parse - options = {} - banner = "Usage: pkg-svr {create|register|gen-snapshot|sync|add-dist|spkg-path|remove|remove-pkg|list|help} ..." + "\n" \ - + "\t" + "pkg-svr create -i -d [-u ] [-l ] " + "\n" \ - + "\t" + "pkg-svr add-dist -i -d [-u ] [-c] " + "\n" \ - + "\t" + "pkg-svr remove -i " + "\n" \ - + "\t" + "pkg-svr register -i -d -p -s [-g] [-t] " + "\n" \ - + "\t" + "pkg-svr remove-pkg -i -d -p " + "\n" \ - + "\t" + "pkg-svr gen-snapshot -i -d [-n ] [-b ] [-p ] " + "\n" \ - + "\t" + "pkg-svr sync -i -d [-f] " + "\n" \ - + "\t" + "pkg-svr spkg-path -i -d -s " + "\n" \ - + "\t" + "pkg-svr list [-i ] " + "\n" - - optparse = OptionParser.new do|opts| - # Set a banner, displayed at the top - # of the help screen. - - opts.banner = banner - - opts.on( '-i', '--id ', 'package server id' ) do|name| - options[:id] = name - end - +def option_parse + options = {} + banner = "Package-server administer service command-line tool." + "\n" \ + + "\n" + "Usage: pkg-svr [OPTS] or pkg-svr (-h|-v)" + "\n" \ + + "\n" + "Subcommands:" + "\n" \ + + "\t" + "create Create a package-server." + "\n" \ + + "\t" + "add-dist Add a distribution to package-server." + "\n" \ + + "\t" + "add-os Add supported os." + "\n" \ + + "\t" + "register Register a package in package-server." + "\n" \ + + "\t" + "remove Remove a package-server." + "\n" \ + + "\t" + "remove-dist Remove a distribution to package-server." + "\n" \ + + "\t" + "remove-pkg Remove a package in package-server." + "\n" \ + + "\t" + "remove-snapshot Remove a snapshot in package-server." + "\n" \ + + "\t" + "gen-snapshot Generate a snapshot in package-server." + "\n" \ + + "\t" + "sync Synchronize the package-server from parent package server." + "\n" \ + + "\t" + "start Start the package-server." + "\n" \ + + "\t" + "stop Stop the package-server." + "\n" \ + + "\t" + "clean Delete unneeded package files in package-server." + "\n" \ + + "\t" + "list Show all pack" + "\n" \ + + "\n" + "Subcommand usage:" + "\n" \ + + "\t" + "pkg-svr create -n -d [-u ] [-l ] " + "\n" \ + + "\t" + "pkg-svr add-dist -n -d [-u ] [--clone] " + "\n" \ + + "\t" + "pkg-svr add-os -n -d -o " + "\n" \ + + "\t" + "pkg-svr register -n -d -P [--gen] [--test] " + "\n" \ + + "\t" + "pkg-svr remove -n " + "\n" \ + + "\t" + "pkg-svr remove-dist -n -d " + "\n" \ + + "\t" + "pkg-svr remove-pkg -n -d -P [-o ] " + "\n" \ + + "\t" + "pkg-svr remove-snapshot -n -d -s " + "\n" \ + + "\t" + "pkg-svr gen-snapshot -n -d -s [-b ] " + "\n" \ + + "\t" + "pkg-svr sync -n -d -s [--force] " + "\n" \ + + "\t" + "pkg-svr clean -n -d [-s ] " + "\n" \ + + "\t" + "pkg-svr start -n -p [-w ]" + "\n" \ + + "\t" + "pkg-svr stop -n -p [-w ]" + "\n" \ + + "\t" + "pkg-svr list [-n ] " + "\n" \ + + "\n" + "Options:" + "\n" + + optparse = OptionParser.new(nil, 32, ' '*8) do|opts| + # Set a banner, displayed at the top + # of the help screen. + + opts.banner = banner + + opts.on( '-n', '--name ', 'package server name' ) do|name| + options[:id] = name + end + opts.on( '-d', '--dist ', 'package server distribution' ) do|dist| - options[:dist] = dist - end - - opts.on( '-u', '--url ', 'remote server address' ) do|url| - options[:url] = url - end - + options[:dist] = dist + end + + opts.on( '-u', '--url ', 'remote server url: http://127.0.0.1/dibs/unstable' ) do|url| + options[:url] = url + end + opts.on( '-o', '--os ', 'target operating system' ) do|os| - options[:os] = os - end - - opts.on( '-p', '--bpackage ', 'binary package file path list' ) do|bpkgs| - options[:bpkgs] = [] - list = bpkgs.tr(" \t","").split(",") - list.each do |l| - # TODO: is not working - #reg = Regexp.new(l) - #Dir.entries(Utils::WORKING_DIR).select{|x| x =~ reg}.each do |ls| - # options[:bpkgs].push ls - #end - if l.start_with? "~" then l = Utils::HOME + l.delete("~") end - options[:bpkgs].push l - end - end - - opts.on( '-s', '--spackage ', 'source package file path ' ) do|spkgs| - options[:spkgs] = [] - list = spkgs.tr(" \t","").split(",") - list.each do |l| + options[:os] = os + end + + opts.on( '-P', '--pkgs ', 'package file path list' ) do|pkgs| + if not Utils.multi_argument_test( pkgs, "," ) then + raise ArgumentError, "Package variable parsing error : #{pkgs}" + end + list = pkgs.tr(" \t","").split(",") + list.each do |l| if l.start_with? "~" then l = Utils::HOME + l.delete("~") end - options[:spkgs].push l - end - end - - opts.on( '-g', '--generate', 'snapshot is generate' ) do - options[:gensnap] = true - end - - opts.on( '-n', '--sname ', 'snapshot name' ) do|snap| - options[:snap] = snap - end - - opts.on( '-b', '--bsnapshot ', 'base snapshot name' ) do|bsnap| - options[:bsnap] = bsnap - end - - opts.on( '-l', '--location ', 'server location' ) do|loc| - options[:loc] = loc - end - - opts.on( '-f', '--force', 'force update pkg file' ) do - options[:force] = true - end - - opts.on( '-t', '--test', 'upload for test' ) do - options[:test] = true - end - - opts.on( '-c', '--clone', 'clone mode' ) do - options[:clone] = true - end - - opts.on( '-h', '--help', 'display this information' ) do - puts opts + options[:pkgs].push l + end + end + + opts.on( '-s', '--snapshot ', 'a snapshot name or snapshot list' ) do|snaplist| + if not Utils.multi_argument_test( snaplist, "," ) then + raise ArgumentError, "Snapshot variable parsing error : #{snaplist}" + end + options[:snaps] = snaplist.split(",") + end + + opts.on( '-b', '--base ', 'base snapshot name' ) do|bsnap| + options[:bsnap] = bsnap + end + + opts.on( '-l', '--loc ', 'server location' ) do|loc| + options[:loc] = loc + end + + opts.on( '-p', '--port ', 'port number' ) do|port| + options[:port] = port + end + + opts.on( '-w', '--passwd ', 'password for package server' ) do|passwd| + options[:passwd] = passwd + end + + opts.on( '--clone', 'clone mode' ) do + options[:clone] = true + end + + opts.on( '--force', 'force update pkg file' ) do + options[:force] = true + end + + opts.on( '--test', 'upload for test' ) do + options[:test] = true + end + + opts.on( '--gen', 'generate snapshot' ) do + options[:gensnap] = true + end + + opts.on( '-h', '--help', 'display help' ) do + puts opts exit - end - - end - - cmd = ARGV[0] - - if cmd.eql? "create" or cmd.eql? "register" or cmd.eql? "sync" \ - or cmd.eql? "gen-snapshot" or cmd.eql? "add-dist" \ - or cmd.eql? "spkg-path" or cmd.eql? "remove" \ - or cmd.eql? "list" or cmd.eql? "remove-pkg" or cmd =~ /(help)|(-h)|(--help)/ then - if cmd.eql? "help" then ARGV[0] = "-h" end - options[:cmd] = ARGV[0] - else - raise ArgumentError, banner - end - - optparse.parse! - - # default value setting + end + + opts.on( '-v', '--version', 'display version' ) do + puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version() + exit + end + end + + cmd = ARGV[0] + + if cmd.eql? "create" or cmd.eql? "sync" \ + or cmd.eql? "register" \ + or cmd.eql? "gen-snapshot" \ + or cmd.eql? "add-dist" or cmd.eql? "add-os" \ + or cmd.eql? "remove" or cmd.eql? "remove-dist" \ + or cmd.eql? "remove-pkg" or cmd.eql? "remove-snapshot" \ + or cmd.eql? "start" or cmd.eql? "stop" or cmd.eql? "clean" \ + or cmd.eql? "list" \ + or cmd =~ /(-v)|(--version)/ \ + or cmd =~ /(help)|(-h)|(--help)/ then + if cmd.eql? "help" then ARGV[0] = "-h" end + options[:cmd] = ARGV[0] + else + raise ArgumentError, "Usage: pkg-svr [OPTS] or pkg-svr -h" + end + + # default value setting set_default options - # option error check + optparse.parse! + + # option error check option_error_check options - return options -end + return options +end diff --git a/test/bin/bin_0.0.0_linux.zip b/test/bin/bin_0.0.0_linux.zip new file mode 100644 index 0000000..9880da1 Binary files /dev/null and b/test/bin/bin_0.0.0_linux.zip differ diff --git a/test/bin/bin_0.0.0_ubuntu-32.zip b/test/bin/bin_0.0.0_ubuntu-32.zip new file mode 100644 index 0000000..d462bfe Binary files /dev/null and b/test/bin/bin_0.0.0_ubuntu-32.zip differ diff --git a/test/bin/bin_0.0.1_linux.zip b/test/bin/bin_0.0.1_linux.zip new file mode 100644 index 0000000..c6a9588 Binary files /dev/null and b/test/bin/bin_0.0.1_linux.zip differ diff --git a/test/bin/bin_0.0.1_ubuntu-32.zip b/test/bin/bin_0.0.1_ubuntu-32.zip new file mode 100644 index 0000000..9c21aca Binary files /dev/null and b/test/bin/bin_0.0.1_ubuntu-32.zip differ diff --git a/test/bin/src.tar.gz b/test/bin/src.tar.gz new file mode 100644 index 0000000..c41dcd8 Binary files /dev/null and b/test/bin/src.tar.gz differ diff --git a/test/build-server.basic1/build-cli-01.testcase b/test/build-server.basic1/build-cli-01.testcase new file mode 100644 index 0000000..90e5080 --- /dev/null +++ b/test/build-server.basic1/build-cli-01.testcase @@ -0,0 +1,43 @@ +#PRE-EXEC +#EXEC +../../build-cli -h +#POST-EXEC +#EXPECT +Requiest service to build-server command-line tool. + +Usage: build-cli [OPTS] or build-cli (-h|-v) + +Subcommands: +build Build and create package. +resolve Request change to resolve-status for build-conflict. +query Query information about build-server. +query-system Query system information about build-server. +query-project Query project information about build-server. +query-job Query job information about build-server. +cancel Cancel a building project. +register Register the package to the build-server. + +Subcommand usage: +build-cli build -N -d [-o ] [-w ] [--async] [-D ] [-U user-email] [-V] +build-cli resolve -N -d [-o ] [-w ] [--async] [-D ] [-U user-email] [-V] +build-cli query -d +build-cli query-system -d +build-cli query-project -d +build-cli query-job -d +build-cli cancel -j -d [-w ] +build-cli register -P -d [-t ] [-w ] [-D ] [-U user-email] + +Options: +-N, --project project name +-d, --address build server address: 127.0.0.1:2224 +-o, --os target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64 +--async asynchronous job +-j, --job job number +-w, --passwd password for managing project +-P, --pkg package file path +-D, --dist distribution name +-t, --ftp ftp server url: ftp://dibsftp:dibsftp@127.0.0.1 +-U, --user user email infomation +-V, --verbose verbose mode +-h, --help display help +-v, --version display version diff --git a/test/build-server.basic1/build-cli-02.testcase b/test/build-server.basic1/build-cli-02.testcase new file mode 100644 index 0000000..4d821bd --- /dev/null +++ b/test/build-server.basic1/build-cli-02.testcase @@ -0,0 +1,29 @@ +#PRE-EXEC +#EXEC +../../build-cli query -d 127.0.0.1:2223 +#POST-EXEC +#EXPECT +* SYSTEM INFO * +HOST-OS: ubuntu-32 +MAX_WORKING_JOBS: 2 + +* FTP * +FTP_ADDR: +FTP_USERNAME: + +* SUPPORTED OS LIST * +ubuntu-32 +windows-32 + +* FRIEND SERVER LIST (WAIT|WORK/MAX) jobs [transfer count] * + + +* PROJECT(S) * +testa NORMAL +testa1 NORMAL +testb NORMAL +testc NORMAL +testd NORMAL +teste REMOTE + +* JOB(S) * diff --git a/test/build-server.basic1/build-cli-03.testcase b/test/build-server.basic1/build-cli-03.testcase new file mode 100644 index 0000000..b084d40 --- /dev/null +++ b/test/build-server.basic1/build-cli-03.testcase @@ -0,0 +1,30 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testa" diff --git a/test/build-server.basic1/build-cli-03_1.testcase b/test/build-server.basic1/build-cli-03_1.testcase new file mode 100644 index 0000000..5324ae3 --- /dev/null +++ b/test/build-server.basic1/build-cli-03_1.testcase @@ -0,0 +1,28 @@ +#PRE-EXEC +echo "This is the test case for omitting os" +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P a +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.basic1/build-cli-04.testcase b/test/build-server.basic1/build-cli-04.testcase new file mode 100644 index 0000000..977d486 --- /dev/null +++ b/test/build-server.basic1/build-cli-04.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N non_exist_project -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Error: Project not found!: non_exist_project on BASE diff --git a/test/build-server.basic1/build-cli-05.testcase b/test/build-server.basic1/build-cli-05.testcase new file mode 100644 index 0000000..0072e13 --- /dev/null +++ b/test/build-server.basic1/build-cli-05.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N testa -d 127.0.0.1:11113 -o ubuntu-32 +#POST-EXEC +#EXPECT +Connection to server failed! diff --git a/test/build-server.basic1/build-cli-06.testcase b/test/build-server.basic1/build-cli-06.testcase new file mode 100644 index 0000000..1682338 --- /dev/null +++ b/test/build-server.basic1/build-cli-06.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N testa -d 111.11q.111.111:1111 -o ubuntu-32 +#POST-EXEC +#EXPECT +Connection to server failed! diff --git a/test/build-server.basic1/build-cli-07.testcase b/test/build-server.basic1/build-cli-07.testcase new file mode 100644 index 0000000..10e64d4 --- /dev/null +++ b/test/build-server.basic1/build-cli-07.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +echo "testa project is already built and uploaded in previeous testcase" +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Error: Version must be increased : +Error: Job is stopped by ERROR diff --git a/test/build-server.basic1/build-cli-08.testcase b/test/build-server.basic1/build-cli-08.testcase new file mode 100644 index 0000000..6d08be1 --- /dev/null +++ b/test/build-server.basic1/build-cli-08.testcase @@ -0,0 +1,32 @@ +#PRE-EXEC +echo "Assume testa project is already built and uploaded in previeous testcase" +#EXEC +../../build-cli build -N testb -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: * a +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... b_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testb" diff --git a/test/build-server.basic1/build-cli-09.testcase b/test/build-server.basic1/build-cli-09.testcase new file mode 100644 index 0000000..b20cb5b --- /dev/null +++ b/test/build-server.basic1/build-cli-09.testcase @@ -0,0 +1,19 @@ +#PRE-EXEC +echo "if build-dep package does not exist in server, will show the error" +echo "Assume testa/testb project is already built and uploaded in previeous testcase" +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P b +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P a +#EXEC +../../build-cli build -N testb -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Error: Unmet dependency found! +Error: * a(ubuntu-32) for build-dependency +Error: Job is stopped by ERROR diff --git a/test/build-server.basic1/build-cli-10.testcase b/test/build-server.basic1/build-cli-10.testcase new file mode 100644 index 0000000..c585766 --- /dev/null +++ b/test/build-server.basic1/build-cli-10.testcase @@ -0,0 +1,32 @@ +#PRE-EXEC +echo "This is the test case for omitting os" +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P a +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testa" diff --git a/test/build-server.basic1/build-cli-11.testcase b/test/build-server.basic1/build-cli-11.testcase new file mode 100644 index 0000000..beb3e82 --- /dev/null +++ b/test/build-server.basic1/build-cli-11.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +echo "if there doe not exist server to build, error" +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o windows-32 +#POST-EXEC +#EXPECT +Info: Added new job "5" for windows-32! +Info: Initializing job... +Error: No servers that are able to build your packages. +Error: Host-OS (windows-32) is not supported in build server. +Error: Job is stopped by ERROR diff --git a/test/build-server.basic1/build-cli-12.testcase b/test/build-server.basic1/build-cli-12.testcase new file mode 100644 index 0000000..a0b9e6f --- /dev/null +++ b/test/build-server.basic1/build-cli-12.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +echo "wrong os name in build command" +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P a +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o wrong_os_name +#POST-EXEC +#EXPECT +Error: Unsupported OS name used!: wrong_os_name +Supported OS list. +* ubuntu-32 +* windows-32 diff --git a/test/build-server.basic1/build-cli-12_1.testcase b/test/build-server.basic1/build-cli-12_1.testcase new file mode 100644 index 0000000..cccfe9f --- /dev/null +++ b/test/build-server.basic1/build-cli-12_1.testcase @@ -0,0 +1,10 @@ +#PRE-EXEC +echo "wrong os name in resolve command" +#EXEC +../../build-cli resolve -N testa -d 127.0.0.1:2223 -o wrong_os_name +#POST-EXEC +#EXPECT +Error: Unsupported OS name used!: wrong_os_name +Supported OS list. +* ubuntu-32 +* windows-32 diff --git a/test/build-server.basic1/build-cli-13.testcase b/test/build-server.basic1/build-cli-13.testcase new file mode 100644 index 0000000..59fd045 --- /dev/null +++ b/test/build-server.basic1/build-cli-13.testcase @@ -0,0 +1,38 @@ +#PRE-EXEC +echo "Assume that testc project has the password (1111)" +echo "Assume that testa,testb which are depended by testc are built and uploaded" +echo "For, work around solution, removed cache" +rm -rf buildsvr01/projects/testa/cache +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 +../../build-cli build -N testb -d 127.0.0.1:2223 -o ubuntu-32 +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -w 1111 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: * a +Info: * b +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... c_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testc" diff --git a/test/build-server.basic1/build-cli-14.testcase b/test/build-server.basic1/build-cli-14.testcase new file mode 100644 index 0000000..df9fff2 --- /dev/null +++ b/test/build-server.basic1/build-cli-14.testcase @@ -0,0 +1,8 @@ +#PRE-EXEC +echo "Assume that testc project has the password (1111)" +echo "Assume that testa,testb which are depended by testc are built and uploaded" +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Error: Project password required!: Use -w option to input your project password diff --git a/test/build-server.basic1/build-cli-15.testcase b/test/build-server.basic1/build-cli-15.testcase new file mode 100644 index 0000000..9b7cd98 --- /dev/null +++ b/test/build-server.basic1/build-cli-15.testcase @@ -0,0 +1,8 @@ +#PRE-EXEC +echo "Assume that testc project has the password (1111)" +echo "Assume that testa,testb which are depended by testc are built and uploaded" +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -w 2222 -o ubuntu-32 +#POST-EXEC +#EXPECT +Error: Project password not matched! diff --git a/test/build-server.basic1/build-cli-16.testcase b/test/build-server.basic1/build-cli-16.testcase new file mode 100644 index 0000000..1f798aa --- /dev/null +++ b/test/build-server.basic1/build-cli-16.testcase @@ -0,0 +1,8 @@ +#PRE-EXEC +../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P c +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -w 1111 --async -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Above job(s) will be processed asynchronously! diff --git a/test/build-server.basic1/build-cli-17.testcase b/test/build-server.basic1/build-cli-17.testcase new file mode 100644 index 0000000..9653e45 --- /dev/null +++ b/test/build-server.basic1/build-cli-17.testcase @@ -0,0 +1,40 @@ +#PRE-EXEC +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P c +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P b +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable -P a +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 --async -o ubuntu-32 +sleep 1 +../../build-cli build -N testb -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Above job(s) will be processed asynchronously! +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Waiting for finishing following jobs: +Info: * +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: * a +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... b_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testb" diff --git a/test/build-server.basic1/build-cli-18.testcase b/test/build-server.basic1/build-cli-18.testcase new file mode 100644 index 0000000..32218a2 --- /dev/null +++ b/test/build-server.basic1/build-cli-18.testcase @@ -0,0 +1,31 @@ +#PRE-EXEC +echo "reverse fail" +#EXEC +rm -rf git01/a +cd git01;tar xf a_v2.tar.gz +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.2_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: * Will check reverse-build for projects: testb(ubuntu-32) +Info: * Added new job for reverse-build ... testb(ubuntu-32) +Info: * Reverse-build FAIL ... testb(ubuntu-32) +Error: Job is stopped by ERROR diff --git a/test/build-server.basic1/build-cli-19.testcase b/test/build-server.basic1/build-cli-19.testcase new file mode 100644 index 0000000..076004e --- /dev/null +++ b/test/build-server.basic1/build-cli-19.testcase @@ -0,0 +1,16 @@ +#PRE-EXEC +#EXEC +../../build-cli query-system -d 127.0.0.1:2223 +#POST-EXEC +#EXPECT +* SYSTEM INFO * +HOST-OS: +MAX_WORKING_JOBS: + +* FTP * +FTP_ADDR: +FTP_USERNAME: + +* SUPPORTED OS LIST * +ubuntu-32 +windows-32 diff --git a/test/build-server.basic1/build-cli-20.testcase b/test/build-server.basic1/build-cli-20.testcase new file mode 100644 index 0000000..e475cf8 --- /dev/null +++ b/test/build-server.basic1/build-cli-20.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-cli query-project -d 127.0.0.1:2223 +#POST-EXEC +#EXPECT +* PROJECT(S) * diff --git a/test/build-server.basic1/build-cli-21.testcase b/test/build-server.basic1/build-cli-21.testcase new file mode 100644 index 0000000..5de4383 --- /dev/null +++ b/test/build-server.basic1/build-cli-21.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-cli query-job -d 127.0.0.1:2223 +#POST-EXEC +#EXPECT +* JOB(S) * diff --git a/test/build-server.basic1/build-cli-22.testcase b/test/build-server.basic1/build-cli-22.testcase new file mode 100644 index 0000000..9ee83c9 --- /dev/null +++ b/test/build-server.basic1/build-cli-22.testcase @@ -0,0 +1,16 @@ +#PRE-EXEC +echo "Trying to upload a_0.0.1 with different commit-id is already uploaded" +rm -rf git01/c +cd git01;tar xf c_v1_1.tar.gz +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -o ubuntu-32 -w 1111 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Error: Source code has been changed without increasing version! +Error: * Version : +Error: * Before : +Error: * Current : +Error: Job is stopped by ERROR diff --git a/test/build-server.basic1/build-cli-23.testcase b/test/build-server.basic1/build-cli-23.testcase new file mode 100644 index 0000000..44ff734 --- /dev/null +++ b/test/build-server.basic1/build-cli-23.testcase @@ -0,0 +1,25 @@ +#PRE-EXEC +cd git01;tar xf a_v2.tar.gz +cd git01;tar xf b_v2.tar.gz +cd git01;tar xf c_v2.tar.gz +#EXEC +../../build-cli build -N testa,testb,testc -d 127.0.0.1:2223 -o ubuntu-32 -w 1111 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Invoking a thread for MULTI-BUILD Job +Info: New Job +Info: Added new job "testa" for ubuntu-32! +Info: Added new job "testb" for ubuntu-32! +Info: Added new job "testc" for ubuntu-32! +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.basic1/build-cli-24.testcase b/test/build-server.basic1/build-cli-24.testcase new file mode 100644 index 0000000..de1b348 --- /dev/null +++ b/test/build-server.basic1/build-cli-24.testcase @@ -0,0 +1,12 @@ +#PRE-EXEC +echo "This test case must be execute right after testcase 22" +#EXEC +../../build-cli build -N testa,testb,testc -d 127.0.0.1:2223 -o ubuntu-32 -w 1111 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Failed to initialize sub-job +Info: Failed to initialize sub-job +Info: Failed to initialize sub-job +Error: Job is stopped by ERROR diff --git a/test/build-server.basic1/build-cli-25.testcase b/test/build-server.basic1/build-cli-25.testcase new file mode 100644 index 0000000..adaeb98 --- /dev/null +++ b/test/build-server.basic1/build-cli-25.testcase @@ -0,0 +1,20 @@ +#PRE-EXEC +cd git01;tar xf a_v3.tar.gz +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32,windows-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Invoking a thread for MULTI-BUILD Job +Info: New Job +Info: Added new job "testa" for ubuntu-32! +Info: Added new job "testa" for windows-32! +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.basic1/build-cli-26.testcase b/test/build-server.basic1/build-cli-26.testcase new file mode 100644 index 0000000..eb0965c --- /dev/null +++ b/test/build-server.basic1/build-cli-26.testcase @@ -0,0 +1,45 @@ +#PRE-EXEC +echo "testa, testb: build because of version change" +echo "testc, testa1, testd: rebuild with same version" + +cd git01;tar xf a_v4.tar.gz +cd git01;tar xf b_v4.tar.gz +cd git01;tar xf c_v4.tar.gz +#EXEC +../../build-svr fullbuild -n testserver3 +#POST-EXEC +#EXPECT +Info: Initializing job... +Info: Invoking a thread for MULTI-BUILD Job +Info: New Job +Info: Added new job +Info: Added new job +Info: Added new job +Info: Added new job +Info: Added new job +Info: Added new job +Info: Added new job +Info: Added new job +Info: Added new job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: * Sub-Job +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.basic1/build-cli-27.testcase b/test/build-server.basic1/build-cli-27.testcase new file mode 100644 index 0000000..66eb1cf --- /dev/null +++ b/test/build-server.basic1/build-cli-27.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +cd git01;tar xf c_v5.tar.gz +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -o li_* -w 1111 +#POST-EXEC +#EXPECT +Error: Unsupported OS name used!: There is no OS name matched. diff --git a/test/build-server.basic1/build-cli-28.testcase b/test/build-server.basic1/build-cli-28.testcase new file mode 100644 index 0000000..27dfb11 --- /dev/null +++ b/test/build-server.basic1/build-cli-28.testcase @@ -0,0 +1,33 @@ +#PRE-EXEC +echo "wild card" +#EXEC +../../build-cli build -N testc -d 127.0.0.1:2223 -o ubuntu-* -w 1111 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: * a +Info: * b +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... c_0.0.5_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testc" diff --git a/test/build-server.basic1/build-cli-29.testcase b/test/build-server.basic1/build-cli-29.testcase new file mode 100644 index 0000000..47d1580 --- /dev/null +++ b/test/build-server.basic1/build-cli-29.testcase @@ -0,0 +1,38 @@ +#PRE-EXEC +echo "reverse success" +#EXEC +rm -rf git01/a +cd git01;tar xf a_v5.tar.gz +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.5_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: * Will check reverse-build for projects: +Info: * Added new job for reverse-build ... +Info: * Added new job for reverse-build ... +Info: * Reverse-build OK ... +Info: * Reverse-build OK ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testa" diff --git a/test/build-server.basic1/build-cli-30.testcase b/test/build-server.basic1/build-cli-30.testcase new file mode 100644 index 0000000..2fe774e --- /dev/null +++ b/test/build-server.basic1/build-cli-30.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +echo "user check" +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 -U xxuser@user +#POST-EXEC +#EXPECT +Error: User account not found!: xxuser@user diff --git a/test/build-server.basic1/buildsvr.init b/test/build-server.basic1/buildsvr.init new file mode 100755 index 0000000..72cf1fe --- /dev/null +++ b/test/build-server.basic1/buildsvr.init @@ -0,0 +1,58 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi + +if [ ! "$DB_PASSWD" ] ; then + read -p "Insert DB password: " input + export DB_PASSWD=$input +else + echo $DB_PASSWD +fi + +rm -rf buildsvr01 +rm -rf git01 +rm -rf bin +rm -rf ~/.build_tools/build_server/testserver3 + +../../build-svr remove -n testserver3 +mkdir buildsvr01 +cd buildsvr01 +${RUBY} ../../../build-svr create -n testserver3 +echo "DROP DATABASE testserver3;" > a +mysql -u root -p --password=$DB_PASSWD -h localhost < a +${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD +rm -f a +cd .. +${RUBY} ../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333 +${RUBY} ../../build-svr add-svr -n testserver3 -d 127.0.0.1:2224 +${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32 +${RUBY} ../../build-svr add-os -n testserver3 -o windows-32 +${RUBY} ../../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testc -g `pwd`/git01/c -b master -w 1111 +${RUBY} ../../build-svr add-prj -n testserver3 -N testd -g `pwd`/git01/d -b master -o ubuntu-32 +${RUBY} ../../build-svr add-prj -n testserver3 -N teste -P bin +${RUBY} ../../build-svr add-prj -n testserver3 -N testa1 -g `pwd`/git01/a1 -b master + +mkdir -p git01 +cp ../git01/*.tar.gz git01/ +cd git01 +rm -rf a +rm -rf a1 +rm -rf b +rm -rf c +rm -rf d +tar xvf a_v1.tar.gz +tar xvf b_v1.tar.gz +tar xvf c_v1.tar.gz +tar xvf d_v0.tar.gz +tar xvf a1_v1.tar.gz +cd .. + +mkdir -p bin +cp ../bin/* bin/ + +${RUBY} ../../pkg-svr register -n pkgsvr01 -d unstable -P bin/bin_0.0.0_ubuntu-32.zip + +${RUBY} ../../build-svr start -n testserver3 -p 2223 --CHILD diff --git a/test/build-server.basic1/pkgsvr.init b/test/build-server.basic1/pkgsvr.init new file mode 100755 index 0000000..6973d9e --- /dev/null +++ b/test/build-server.basic1/pkgsvr.init @@ -0,0 +1,10 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi +rm -rf ~/.build_tools/pkg_server/pkgsvr01 +rm -rf `pwd`/pkgsvr01 +${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32 +${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333 diff --git a/test/build-server.basic1/testsuite b/test/build-server.basic1/testsuite new file mode 100644 index 0000000..b5b5903 --- /dev/null +++ b/test/build-server.basic1/testsuite @@ -0,0 +1,31 @@ +build-cli-01.testcase +build-cli-02.testcase +build-cli-03.testcase +build-cli-04.testcase +build-cli-05.testcase +build-cli-06.testcase +build-cli-07.testcase +build-cli-08.testcase +build-cli-09.testcase +build-cli-10.testcase +build-cli-11.testcase +build-cli-12.testcase +build-cli-12_1.testcase +build-cli-13.testcase +build-cli-14.testcase +build-cli-15.testcase +build-cli-16.testcase +build-cli-17.testcase +build-cli-18.testcase +build-cli-19.testcase +build-cli-20.testcase +build-cli-21.testcase +build-cli-22.testcase +build-cli-23.testcase +build-cli-24.testcase +build-cli-25.testcase +build-cli-26.testcase +build-cli-27.testcase +build-cli-28.testcase +build-cli-29.testcase +build-cli-30.testcase diff --git a/test/build-server.basic2/build-svr-01.testcase b/test/build-server.basic2/build-svr-01.testcase new file mode 100644 index 0000000..f9617b1 --- /dev/null +++ b/test/build-server.basic2/build-svr-01.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf ~/.build_tools/build_server/testserver3 +rm -rf buildsvr01 +mkdir buildsvr01 +#EXEC +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://ftpuser:ftpuser@172.21.111.124 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Created new build server: "testserver3" diff --git a/test/build-server.basic2/build-svr-02.testcase b/test/build-server.basic2/build-svr-02.testcase new file mode 100644 index 0000000..271b3c0 --- /dev/null +++ b/test/build-server.basic2/build-svr-02.testcase @@ -0,0 +1,79 @@ +#PRE-EXEC +#EXEC +../../build-svr -h +#POST-EXEC +#EXPECT +Build-server administer service command-line tool. + +Usage: build-svr [OPTS] or build-svr (-h|-v) + +Subcommands: +create Create the build-server. +remove Remove the build-server. +migrate build-server DB migrate. +start Start the build-server. +stop Stop the build-server. +upgrade Upgrade the build-server include friends. +add-svr Add remote build/package server for support multi-OS or distribute build job. +remove-svr Remove remote build/package server for support multi-OS or distribute build job. +add-os Add supported OS. +remove-os Remove supported OS. +add-dist Add distribution. +remove-dist Remove distribution. +lock-dist Lock distribution. +unlock-dist Unlock distribution. +add-sync Add package repository URL to synchronize with. +remove-sync Remove package repository URL. +add-prj Add project to build. +remove-prj Remove project. +register Register the package to the build-server. +fullbuild Build all your projects and upload them to package server. +query Show build server configuration. +set-attr Set build server atribute. +get-attr Get build server atribute. + +Subcommand usage: +build-svr create -n [-t ] +build-svr remove -n +build-svr migrate -n [--dsn [--dbuser --dbpassword ] ] +build-svr start -n -p +build-svr stop -n +build-svr upgrade -n +build-svr add-svr -n -d +build-svr remove-svr -n -d +build-svr add-os -n -o +build-svr remove-os -n -o +build-svr add-dist -n -D -u -d +build-svr remove-dist -n -D +build-svr lock-dist -n -D +build-svr unlock-dist -n -D +build-svr add-sync -n -u [--dist ] +build-svr remove-sync -n -u [--dist ] +build-svr add-prj -n -N (-g -b |-P ) [-w ] [-o ] [--dist ] +build-svr remove-prj -n -N [--dist ] +build-svr fullbuild -n [--dist ] +build-svr register -n -P [--dist ] +build-svr query -n +build-svr set-attr -n -A -V +build-svr get-attr -n -A + +Options: +-n, --name build server name +-u, --url package server url: http://127.0.0.1/dibs/unstable +-d, --address server address: 127.0.0.1:2224 +-p, --port server port number: 2224 +-P, --pkg package file path or name +-o, --os ex) ubuntu-32,windows-32 +-N, --pname project name +-g, --git git repository +-b, --branch git branch +-D, --dist distribution name +-w, --passwd password for managing project +-t, --ftp ftp server url: ftp://dibsftp:dibsftp@127.0.0.1:1024 +-A, --attr attribute +--dsn Data Source Name ex) mysql:host=localhost;database=test +--dbuser DB user id +--dbpassword DB password +-V, --value value +-h, --help display this information +-v, --version display version diff --git a/test/build-server.basic2/build-svr-03.testcase b/test/build-server.basic2/build-svr-03.testcase new file mode 100644 index 0000000..236a9ef --- /dev/null +++ b/test/build-server.basic2/build-svr-03.testcase @@ -0,0 +1,24 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +#EXEC +../../build-svr add-svr -n testserver3 -d 127.0.0.1:2223 +../../build-svr query -n testserver3 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Friend server is added successfully! +* REMOTE SERVER(S) * +* 127.0.0.1:2223 + +* SUPPORTED OS * + +* DISTRIBUTION(S) * +* BASE + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * diff --git a/test/build-server.basic2/build-svr-04.testcase b/test/build-server.basic2/build-svr-04.testcase new file mode 100644 index 0000000..985f511 --- /dev/null +++ b/test/build-server.basic2/build-svr-04.testcase @@ -0,0 +1,12 @@ +#PRE-EXEC +rm -rf ~/.build_tools/build_server/testserver3 +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#EXEC +echo "TEST_TIME=3" >> ~/.build_tools/build_server/testserver3/server.cfg +../../build-svr start -n testserver3 -p 2223 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT diff --git a/test/build-server.basic2/build-svr-05.testcase b/test/build-server.basic2/build-svr-05.testcase new file mode 100644 index 0000000..23d530f --- /dev/null +++ b/test/build-server.basic2/build-svr-05.testcase @@ -0,0 +1,15 @@ +#PRE-EXEC +mkdir buildsvr01 +rm -rf ~/.build_tools/build_server/testserver3 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +../../build-svr start -n testserver3 -p 2223 & +#EXEC +sleep 1 +../../build-svr stop -n testserver3 +sleep 1 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Server will be down! diff --git a/test/build-server.basic2/build-svr-06.testcase b/test/build-server.basic2/build-svr-06.testcase new file mode 100644 index 0000000..b3f62fe --- /dev/null +++ b/test/build-server.basic2/build-svr-06.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#EXEC +../../build-svr stop -n testserver3 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +generating +Server is not running! diff --git a/test/build-server.basic2/build-svr-07.testcase b/test/build-server.basic2/build-svr-07.testcase new file mode 100644 index 0000000..b5518f5 --- /dev/null +++ b/test/build-server.basic2/build-svr-07.testcase @@ -0,0 +1,9 @@ +#PRE-EXEC +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#EXEC +../../build-svr remove -n testserver3 +#POST-EXEC +rm -rf buildsvr01 +#EXPECT +Removed the server diff --git a/test/build-server.basic2/build-svr-08.testcase b/test/build-server.basic2/build-svr-08.testcase new file mode 100644 index 0000000..3ab2171 --- /dev/null +++ b/test/build-server.basic2/build-svr-08.testcase @@ -0,0 +1,12 @@ +#PRE-EXEC +rm -rf ~/.build_tools/build_server/testserver3 +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#EXEC +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Creating server failed. The server id is already exist diff --git a/test/build-server.basic2/build-svr-09.testcase b/test/build-server.basic2/build-svr-09.testcase new file mode 100644 index 0000000..2a301eb --- /dev/null +++ b/test/build-server.basic2/build-svr-09.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-svr remove -n testserverxx +#POST-EXEC +#EXPECT +does not exist! diff --git a/test/build-server.basic2/build-svr-10.testcase b/test/build-server.basic2/build-svr-10.testcase new file mode 100644 index 0000000..1d3f863 --- /dev/null +++ b/test/build-server.basic2/build-svr-10.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-svr start -n testserverxx +#POST-EXEC +#EXPECT +does not exist! diff --git a/test/build-server.basic2/build-svr-11.testcase b/test/build-server.basic2/build-svr-11.testcase new file mode 100644 index 0000000..0b2f399 --- /dev/null +++ b/test/build-server.basic2/build-svr-11.testcase @@ -0,0 +1,13 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +../../build-svr add-os -n testserver3 -o ubuntu-32 +#EXEC +../../build-svr add-prj -n testserver3 -N testa -g test_git -b test_branch +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Adding project succeeded! diff --git a/test/build-server.basic2/build-svr-12.testcase b/test/build-server.basic2/build-svr-12.testcase new file mode 100644 index 0000000..1dcbb18 --- /dev/null +++ b/test/build-server.basic2/build-svr-12.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-svr add-prj -n testserverxxx -N testa -g test_git -b test_branch +#POST-EXEC +#EXPECT +does not exist! diff --git a/test/build-server.basic2/build-svr-13.testcase b/test/build-server.basic2/build-svr-13.testcase new file mode 100644 index 0000000..f87355b --- /dev/null +++ b/test/build-server.basic2/build-svr-13.testcase @@ -0,0 +1,10 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +#EXEC +../../build-svr add-prj -n testserver3 -N testa -g test_git -b test_branch -w 1111 +#POST-EXEC +#EXPECT +Adding project succeeded! diff --git a/test/build-server.basic2/build-svr-14.testcase b/test/build-server.basic2/build-svr-14.testcase new file mode 100644 index 0000000..ce59935 --- /dev/null +++ b/test/build-server.basic2/build-svr-14.testcase @@ -0,0 +1,14 @@ +#PRE-EXEC +rm -rf buildsvr01 +rm -rf ~/.build_tools/build_server/testserver3 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +../../build-svr add-os -n testserver3 -o ubuntu-32 +#EXEC +../../build-svr add-prj -n testserver3 -N testx -g test_git -b test_branch -o ubuntu-32 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Adding project succeeded! diff --git a/test/build-server.basic2/build-svr-15.testcase b/test/build-server.basic2/build-svr-15.testcase new file mode 100644 index 0000000..734b5a7 --- /dev/null +++ b/test/build-server.basic2/build-svr-15.testcase @@ -0,0 +1,19 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#EXEC +../../build-svr register -n testserver3 -P bin/bin_0.0.0_ubuntu-32.zip +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for REGISTER Job +Info: New Job +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.basic2/build-svr-16.testcase b/test/build-server.basic2/build-svr-16.testcase new file mode 100644 index 0000000..b5fe4fc --- /dev/null +++ b/test/build-server.basic2/build-svr-16.testcase @@ -0,0 +1,15 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +../../build-svr register -n testserver3 -P bin/bin_0.0.0_ubuntu-32.zip +#EXEC +../../build-svr register -n testserver3 -P bin/bin_0.0.0_ubuntu-32.zip +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Info: Initializing job... +Info: Checking package version ... +Error: Version must be increased : +Error: Job is stopped by ERROR diff --git a/test/build-server.basic2/build-svr-17.testcase b/test/build-server.basic2/build-svr-17.testcase new file mode 100644 index 0000000..244ce63 --- /dev/null +++ b/test/build-server.basic2/build-svr-17.testcase @@ -0,0 +1,24 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +#EXEC +../../build-svr add-os -n testserver3 -o ubuntu-32 +../../build-svr query -n testserver3 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Target OS is added successfully! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* BASE + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * diff --git a/test/build-server.basic2/build-svr-18.testcase b/test/build-server.basic2/build-svr-18.testcase new file mode 100644 index 0000000..d2517ee --- /dev/null +++ b/test/build-server.basic2/build-svr-18.testcase @@ -0,0 +1,14 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +#EXEC +../../build-svr add-os -n testserver3 -o ubuntu-32 +../../build-svr add-os -n testserver3 -o ubuntu-32 +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +generating +Target OS is added successfully! +Target OS already exists in list! diff --git a/test/build-server.basic2/build-svr-19.testcase b/test/build-server.basic2/build-svr-19.testcase new file mode 100644 index 0000000..5a7ce72 --- /dev/null +++ b/test/build-server.basic2/build-svr-19.testcase @@ -0,0 +1,16 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132 +../../build-svr add-os -n testserver3 -o ubuntu-32 +../../build-svr add-os -n testserver3 -o windows-32 +#EXEC +../../build-svr add-prj -n testserver3 -N new_project -g new_git -b new_branch -o wrong_os_name +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +Unsupported OS name "wrong_os_name" is used! +Check the following supported OS list: + * ubuntu-32 + * windows-32 diff --git a/test/build-server.basic2/build-svr-20.testcase b/test/build-server.basic2/build-svr-20.testcase new file mode 100644 index 0000000..1396b9c --- /dev/null +++ b/test/build-server.basic2/build-svr-20.testcase @@ -0,0 +1,22 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@172.21.111.124 +cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +../../build-svr add-os -n testserver3 -o ubuntu-32 +mkdir -p bin +cp ../bin/bin_0.0.0_ubuntu-32.zip bin/bin_0.0.0_wrongosname.zip +../../build-svr start -n testserver3 -p 2223 & +#EXEC +sleep 1 +../../build-svr register -n testserver3 -P bin/bin_0.0.0_wrongosname.zip +#POST-EXEC +../../build-svr stop -n testserver3 +sleep 1 +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +rm -rf bin/bin/bin_0.0.0_wrongosname.zip +#EXPECT +Info: Initializing job... +Error: Unsupported OS "wrongosname" is used! +Error: Job is stopped by ERROR diff --git a/test/build-server.basic2/build-svr-21.testcase b/test/build-server.basic2/build-svr-21.testcase new file mode 100644 index 0000000..b703113 --- /dev/null +++ b/test/build-server.basic2/build-svr-21.testcase @@ -0,0 +1,20 @@ +#PRE-EXEC +rm -rf buildsvr01 +mkdir buildsvr01 +cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://ftpuser:ftpuser@172.21.111.124 +cd buildsvr01; ../../../build-svr migrate -n testserver3 +#EXEC +../../build-svr set-attr -n testserver3 -A MAX_WORKING_JOBS -V 3 +../../build-svr get-attr -n testserver3 -A MAX_WORKING_JOBS +../../build-svr set-attr -n testserver3 -A XXX +../../build-svr set-attr -n testserver3 -A XXX -V 1 +../../build-svr get-attr -n testserver3 -A XXX + +#POST-EXEC +../../build-svr remove -n testserver3 +rm -rf buildsvr01 +#EXPECT +3 +Usage: build-svr set-attr -n -A -V +Wrong attribute name! +Wrong attribute name! diff --git a/test/build-server.basic2/testsuite b/test/build-server.basic2/testsuite new file mode 100644 index 0000000..05f65d2 --- /dev/null +++ b/test/build-server.basic2/testsuite @@ -0,0 +1,19 @@ +build-svr-01.testcase +build-svr-02.testcase +build-svr-03.testcase +build-svr-04.testcase +build-svr-05.testcase +build-svr-06.testcase +build-svr-07.testcase +build-svr-08.testcase +build-svr-09.testcase +build-svr-10.testcase +build-svr-11.testcase +build-svr-12.testcase +build-svr-13.testcase +build-svr-14.testcase +build-svr-17.testcase +build-svr-18.testcase +build-svr-19.testcase +build-svr-20.testcase +build-svr-21.testcase diff --git a/test/build-server.multi-svr1/01.testcase b/test/build-server.multi-svr1/01.testcase new file mode 100644 index 0000000..21843e1 --- /dev/null +++ b/test/build-server.multi-svr1/01.testcase @@ -0,0 +1,45 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 -D unstable +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Started to build this job... +Info: JobBuilder# +Info: Start to build on remote server... +Info: Sending build request to remote server... +Info: Added new job +Info: Initializing job... +Info: Copying external dependent pkgs... +Info: Invoking a thread for building Job +Info: New Job +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.1_ubuntu-32.zip +Info: Copying log to +Info: Copying result files to +Info: * +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "UNNAMED +Info: Receiving log file from remote server... +Info: Receiving file from remote server : a_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testa" diff --git a/test/build-server.multi-svr1/02.testcase b/test/build-server.multi-svr1/02.testcase new file mode 100644 index 0000000..cbe7440 --- /dev/null +++ b/test/build-server.multi-svr1/02.testcase @@ -0,0 +1,46 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N testb -d 127.0.0.1:2223 -o ubuntu-32 -D unstable +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Started to build this job... +Info: JobBuilder +Info: Start to build on remote server... +Info: Sending build request to remote server... +Info: Added new job +Info: Initializing job... +Info: Copying external dependent pkgs... +Info: Invoking a thread for building Job +Info: New Job +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: * a +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... b_0.0.1_ubuntu-32.zip +Info: Copying log to +Info: Copying result files to +Info: * +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "UNNAMED +Info: Receiving log file from remote server... +Info: Receiving file from remote server : b_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testb" diff --git a/test/build-server.multi-svr1/buildsvr1.init b/test/build-server.multi-svr1/buildsvr1.init new file mode 100755 index 0000000..9b0af28 --- /dev/null +++ b/test/build-server.multi-svr1/buildsvr1.init @@ -0,0 +1,46 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi + +if [ ! "$DB_PASSWD" ] ; then + echo -n "insert Mysql password : " + read input + export DB_PASSWD=$input +else + echo $DB_PASSWD +fi + +rm -rf buildsvr01 +rm -rf git01 +rm -rf bin +rm -rf ~/.build_tools/build_server/testserver3 + +../../build-svr remove -n testserver3 +mkdir buildsvr01 +cd buildsvr01 +${RUBY} ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1 +echo "DROP DATABASE testserver3;" > a +mysql -u root -p --password=$DB_PASSWD -h localhost < a +${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD +rm -f a +cd .. + +${RUBY} ../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333 +${RUBY} ../../build-svr add-svr -n testserver3 -d 127.0.0.1:2224 +${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32 +${RUBY} ../../build-svr add-os -n testserver3 -o windows-32 +${RUBY} ../../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master +${RUBY} ../../build-svr set-attr -n testserver3 -A MAX_WORKING_JOBS -V 0 + +mkdir -p git01 +cp ../git01/*.tar.gz git01/ +cd git01 +rm -rf a +rm -rf b +tar xvf a_v1.tar.gz +tar xvf b_v1.tar.gz +cd .. + +${RUBY} ../../build-svr start -n testserver3 -p 2223 --CHILD diff --git a/test/build-server.multi-svr1/buildsvr2.init b/test/build-server.multi-svr1/buildsvr2.init new file mode 100755 index 0000000..56b8da5 --- /dev/null +++ b/test/build-server.multi-svr1/buildsvr2.init @@ -0,0 +1,26 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi + +if [ ! "$DB_PASSWD" ] ; then + read -p "Insert DB password: " input + export DB_PASSWD=$input +else + echo $DB_PASSWD +fi + +rm -rf buildsvr02 + +../../build-svr remove -n testserver4 +mkdir buildsvr02 +cd buildsvr02 +${RUBY} ../../../build-svr create -n testserver4 +echo "DROP DATABASE testserver4;" > a +mysql -u root -p --password=$DB_PASSWD -h localhost < a +${RUBY} ../../../build-svr migrate -n testserver4 --dsn Mysql:testserver4:localhost --dbuser root --dbpassword $DB_PASSWD +rm -f a +cd .. +${RUBY} ../../build-svr add-dist -n testserver4 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333 + +${RUBY} ../../build-svr start -n testserver4 -p 2224 --CHILD diff --git a/test/build-server.multi-svr1/pkgsvr.init b/test/build-server.multi-svr1/pkgsvr.init new file mode 100755 index 0000000..0cc21e3 --- /dev/null +++ b/test/build-server.multi-svr1/pkgsvr.init @@ -0,0 +1,10 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi +rm -rf ~/.build_tools/pkg_server/pkgsvr01 +rm -rf `pwd`/pkgsvr01 +${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32 +${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333 diff --git a/test/build-server.multi-svr1/testsuite b/test/build-server.multi-svr1/testsuite new file mode 100644 index 0000000..960eff3 --- /dev/null +++ b/test/build-server.multi-svr1/testsuite @@ -0,0 +1,2 @@ +01.testcase +02.testcase diff --git a/test/build-server.multi-svr2/01.testcase b/test/build-server.multi-svr2/01.testcase new file mode 100644 index 0000000..f71a53f --- /dev/null +++ b/test/build-server.multi-svr2/01.testcase @@ -0,0 +1,23 @@ +#PRE-EXEC +#EXEC +../../pkg-svr register -n pkgsvr02 -d unstable -P bin/bin_0.0.1_ubuntu-32.zip +sleep 50 +../../pkg-cli list-rpkg -P bin -u `pwd`/pkgsvr01/unstable +#POST-EXEC +#EXPECT +Archive: bin/bin_0.0.1_ubuntu-32.zip +inflating: +snapshot is generated : +package registed successfully +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +bin (0.0.1) diff --git a/test/build-server.multi-svr2/buildsvr.init b/test/build-server.multi-svr2/buildsvr.init new file mode 100755 index 0000000..b0859c9 --- /dev/null +++ b/test/build-server.multi-svr2/buildsvr.init @@ -0,0 +1,37 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi + +if [ ! "$DB_PASSWD" ] ; then + read -p "Insert DB password: " input + export DB_PASSWD=$input +else + echo $DB_PASSWD +fi + +rm -rf buildsvr01 +rm -rf git01 +rm -rf bin +rm -rf ~/.build_tools/build_server/testserver3 + +../../build-svr remove -n testserver3 +mkdir buildsvr01 +cd buildsvr01 +${RUBY} ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1 +echo "DROP DATABASE testserver3;" > a +mysql -u root -p --password=$DB_PASSWD -h localhost < a +${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD +rm -f a +cd .. + +${RUBY} ../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333 +${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32 +${RUBY} ../../build-svr add-os -n testserver3 -o windows-32 +${RUBY} ../../build-svr add-prj -n testserver3 -N teste -P bin -D unstable -o ubuntu-32 +${RUBY} ../../build-svr add-sync -n testserver3 -u `pwd`/pkgsvr02/unstable -D unstable + +mkdir -p bin +cp ../bin/*.zip ./bin/ + +${RUBY} ../../build-svr start -n testserver3 -p 2223 --CHILD diff --git a/test/build-server.multi-svr2/pkgsvr1.init b/test/build-server.multi-svr2/pkgsvr1.init new file mode 100755 index 0000000..0cc21e3 --- /dev/null +++ b/test/build-server.multi-svr2/pkgsvr1.init @@ -0,0 +1,10 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi +rm -rf ~/.build_tools/pkg_server/pkgsvr01 +rm -rf `pwd`/pkgsvr01 +${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32 +${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333 diff --git a/test/build-server.multi-svr2/pkgsvr2.init b/test/build-server.multi-svr2/pkgsvr2.init new file mode 100755 index 0000000..46ec0a7 --- /dev/null +++ b/test/build-server.multi-svr2/pkgsvr2.init @@ -0,0 +1,10 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi +rm -rf ~/.build_tools/pkg_server/pkgsvr02 +rm -rf `pwd`/pkgsvr02 +${RUBY} ../../pkg-svr create -n pkgsvr02 -d unstable +${RUBY} ../../pkg-svr add-os -n pkgsvr02 -d unstable -o ubuntu-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr02 -d unstable -o windows-32 +${RUBY} ../../pkg-svr start -n pkgsvr02 -p 3334 diff --git a/test/build-server.multi-svr2/testsuite b/test/build-server.multi-svr2/testsuite new file mode 100644 index 0000000..1bb2eb2 --- /dev/null +++ b/test/build-server.multi-svr2/testsuite @@ -0,0 +1 @@ +01.testcase diff --git a/test/build-server.multi_dist1/build-svr2-01.testcase b/test/build-server.multi_dist1/build-svr2-01.testcase new file mode 100644 index 0000000..fb3d879 --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-01.testcase @@ -0,0 +1,23 @@ +#PRE-EXEC +rm -rf buildsvr01 +rm -rf ~/.build_tools/build_server/testserver3 +mkdir buildsvr01 +cd buildsvr01;../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1 +../../build-svr add-os -n testserver3 -o ubuntu-32 +../../build-svr add-os -n testserver3 -o ubuntu-64 +#EXEC +../../build-svr remove-os -n testserver3 -o ubuntu-64 +../../build-svr query -n testserver3 +#POST-EXEC +#EXPECT +Target OS is removed successfully! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * diff --git a/test/build-server.multi_dist1/build-svr2-02.testcase b/test/build-server.multi_dist1/build-svr2-02.testcase new file mode 100644 index 0000000..9298235 --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-02.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +echo "no os" +#EXEC +../../build-svr remove-os -n testserver3 -o ubuntu-644 +#POST-EXEC +#EXPECT +Target OS does not exist in list! diff --git a/test/build-server.multi_dist1/build-svr2-03.testcase b/test/build-server.multi_dist1/build-svr2-03.testcase new file mode 100644 index 0000000..06f96c2 --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-03.testcase @@ -0,0 +1,18 @@ +#PRE-EXEC +#EXEC +../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +../../build-svr query -n testserver3 +#POST-EXEC +#EXPECT +Distribution is added successfully! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * diff --git a/test/build-server.multi_dist1/build-svr2-04.testcase b/test/build-server.multi_dist1/build-svr2-04.testcase new file mode 100644 index 0000000..c667dfc --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-04.testcase @@ -0,0 +1,19 @@ +#PRE-EXEC +../../build-svr add-dist -n testserver3 -D unstable2 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +#EXEC +../../build-svr remove-dist -n testserver3 -D unstable2 +../../build-svr query -n testserver3 +#POST-EXEC +#EXPECT +Distribution is removed successfully! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * diff --git a/test/build-server.multi_dist1/build-svr2-05.testcase b/test/build-server.multi_dist1/build-svr2-05.testcase new file mode 100644 index 0000000..b08491d --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-05.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../../build-svr remove-dist -n testserver3 -D unstable22 +#POST-EXEC +#EXPECT +Distribution does not exist in list! diff --git a/test/build-server.multi_dist1/build-svr2-06.testcase b/test/build-server.multi_dist1/build-svr2-06.testcase new file mode 100644 index 0000000..685d52a --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-06.testcase @@ -0,0 +1,66 @@ +#PRE-EXEC +#EXEC +../../build-svr add-sync -n testserver3 -u http://xxx +../../build-svr query -n testserver3 +../../build-svr add-sync -n testserver3 -D unstable -u http://yyy +../../build-svr query -n testserver3 +../../build-svr remove-sync -n testserver3 -u http://yyy +../../build-svr query -n testserver3 +../../build-svr remove-sync -n testserver3 -D unstable testserver3 -u http://xxx +../../build-svr query -n testserver3 +../../build-svr remove-sync -n testserver3 -D unstable testserver3 -u http://xxxyyyy +#POST-EXEC +#EXPECT +Remote package server is added! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * +* [unstable] http://xxx + +* PROJECT(S) * +Remote package server is added! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * +* [unstable] http://xxx +* [unstable] http://yyy + +* PROJECT(S) * +Remote package server is removed! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * +* [unstable] http://xxx + +* PROJECT(S) * +Remote package server is removed! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * +The server does not exist in list! diff --git a/test/build-server.multi_dist1/build-svr2-07.testcase b/test/build-server.multi_dist1/build-svr2-07.testcase new file mode 100644 index 0000000..6afd8c9 --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-07.testcase @@ -0,0 +1,78 @@ +#PRE-EXEC +../../build-svr add-dist -n testserver3 -D unstable2 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 +#EXEC +../../build-svr add-prj -n testserver3 -N test1 -g test1_git -b test1_branch +../../build-svr query -n testserver3 +../../build-svr add-prj -n testserver3 -D unstable -N test2 -g test1_git -b test1_branch +../../build-svr add-prj -n testserver3 -D unstable2 -N test1 -g test1_git -b test1_branch +../../build-svr query -n testserver3 +../../build-svr remove-prj -n testserver3 -N test1 +../../build-svr query -n testserver3 +../../build-svr remove-prj -n testserver3 -D unstable -N test2 +../../build-svr remove-prj -n testserver3 -D unstable2 -N test1 +../../build-svr query -n testserver3 +../../build-svr remove-prj -n testserver3 -D unstable -N testxxx +#POST-EXEC +../../build-svr remove-dist -n testserver3 -D unstable2 +#EXPECT +Adding project succeeded! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable +* unstable2 + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * +* [unstable] test1 +Adding project succeeded! +Adding project succeeded! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable +* unstable2 + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * +* [unstable] test1 +* [unstable] test2 +* [unstable2] test1 +Removing project succeeded! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable +* unstable2 + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * +* [unstable] test2 +* [unstable2] test1 +Removing project succeeded! +Removing project succeeded! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable +* unstable2 + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * +Removing project failed! diff --git a/test/build-server.multi_dist1/build-svr2-08.testcase b/test/build-server.multi_dist1/build-svr2-08.testcase new file mode 100644 index 0000000..90ef0b4 --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-08.testcase @@ -0,0 +1,21 @@ +#PRE-EXEC +#EXEC +../../build-svr add-prj -n testserver3 -D unstable -N testbin -P bin +../../build-svr query -n testserver3 +../../build-svr remove-prj -n testserver3 -N testbin -D unstable +#POST-EXEC +#EXPECT +Adding project succeeded! +* REMOTE SERVER(S) * + +* SUPPORTED OS * +* ubuntu-32 + +* DISTRIBUTION(S) * +* unstable + +* SYNC PACKAGE SERVER(S) * + +* PROJECT(S) * +* [unstable] testbin +Removing project succeeded! diff --git a/test/build-server.multi_dist1/build-svr2-09.testcase b/test/build-server.multi_dist1/build-svr2-09.testcase new file mode 100644 index 0000000..7c4a92e --- /dev/null +++ b/test/build-server.multi_dist1/build-svr2-09.testcase @@ -0,0 +1,12 @@ +#PRE-EXEC +#EXEC +../../build-svr lock-dist -n testserver3 -D unstable +../../build-svr lock-dist -n testserver3 -D unstable2 +../../build-svr unlock-dist -n testserver3 -D unstable +../../build-svr unlock-dist -n testserver3 -D unstable2 +#POST-EXEC +#EXPECT +Distribution is locked! +Locking distribution failed! +Distribution is unlocked! +Unlocking distribution failed! diff --git a/test/build-server.multi_dist1/testsuite b/test/build-server.multi_dist1/testsuite new file mode 100644 index 0000000..3f955a6 --- /dev/null +++ b/test/build-server.multi_dist1/testsuite @@ -0,0 +1,9 @@ +build-svr2-01.testcase +build-svr2-02.testcase +build-svr2-03.testcase +build-svr2-04.testcase +build-svr2-05.testcase +build-svr2-06.testcase +build-svr2-07.testcase +build-svr2-08.testcase +build-svr2-09.testcase diff --git a/test/build-server.multi_dist2/build-svr3-01.testcase b/test/build-server.multi_dist2/build-svr3-01.testcase new file mode 100644 index 0000000..224c40a --- /dev/null +++ b/test/build-server.multi_dist2/build-svr3-01.testcase @@ -0,0 +1,14 @@ +#PRE-EXEC +#EXEC +../../build-svr register -n testserver3 -D unstable -P bin/bin_0.0.0_ubuntu-32.zip +#POST-EXEC +#EXPECT +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for REGISTER Job +Info: New Job +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.multi_dist2/build-svr3-02.testcase b/test/build-server.multi_dist2/build-svr3-02.testcase new file mode 100644 index 0000000..b25a3de --- /dev/null +++ b/test/build-server.multi_dist2/build-svr3-02.testcase @@ -0,0 +1,56 @@ +#PRE-EXEC +#EXEC +../../build-cli build -N testa -d 127.0.0.1:2223 -D unstable +../../build-cli build -N testa -d 127.0.0.1:2223 -D unstable2 +#POST-EXEC +#EXPECT +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testa" +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... a_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testa" diff --git a/test/build-server.multi_dist2/build-svr3-03.testcase b/test/build-server.multi_dist2/build-svr3-03.testcase new file mode 100644 index 0000000..be7df44 --- /dev/null +++ b/test/build-server.multi_dist2/build-svr3-03.testcase @@ -0,0 +1,28 @@ +#PRE-EXEC +#EXEC +../../build-cli register -d 127.0.0.1:2223 -P bin/bin_0.0.0_ubuntu-32.zip -D unstable2 -t ftp://ftpuser:ftpuser@127.0.0.1 +#POST-EXEC +#EXPECT +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +I, [ +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for REGISTER Job +Info: New Job +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! diff --git a/test/build-server.multi_dist2/build-svr3-04.testcase b/test/build-server.multi_dist2/build-svr3-04.testcase new file mode 100644 index 0000000..fe29a83 --- /dev/null +++ b/test/build-server.multi_dist2/build-svr3-04.testcase @@ -0,0 +1,18 @@ +#PRE-EXEC +#EXEC +../../build-svr fullbuild -n testserver3 -D unstable2 +#POST-EXEC +#EXPECT +Info: Initializing job... +Info: Invoking a thread for MULTI-BUILD Job +Info: New Job +Info: Added new job "testa" for ubuntu-32! +Info: Added new job "testb" for ubuntu-32! +Info: * Sub-Job "testa(ubuntu-32)" has entered "WORKING" state. +Info: * Sub-Job "testa(ubuntu-32)" has entered "FINISHED" state. +Info: * Sub-Job "testb(ubuntu-32)" has entered "WORKING" state. +Info: * Sub-Job "testb(ubuntu-32)" has entered "FINISHED" state. +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed diff --git a/test/build-server.multi_dist2/build-svr3-05.testcase b/test/build-server.multi_dist2/build-svr3-05.testcase new file mode 100644 index 0000000..6836515 --- /dev/null +++ b/test/build-server.multi_dist2/build-svr3-05.testcase @@ -0,0 +1,46 @@ +#PRE-EXEC +../../pkg-svr remove-pkg -n pkgsvr01 -d unstable2 -P b +#EXEC +echo "==" +../../build-svr lock-dist -n testserver3 -D unstable2 +echo "==" +../../build-cli build -N testb -d 127.0.0.1:2223 -D unstable2 +echo "==" +../../build-svr unlock-dist -n testserver3 -D unstable2 +echo "==" +../../build-cli build -N testb -d 127.0.0.1:2223 -D unstable2 +#POST-EXEC +#EXPECT +== +Distribution is locked! +== +Error: Distribution locked!: unstable2 +== +Distribution is unlocked! +== +Info: Added new job +Info: Initializing job... +Info: Checking package version ... +Info: Invoking a thread for building Job +Info: New Job +Info: Checking build dependency ... +Info: Checking install dependency ... +Info: Started to build this job... +Info: JobBuilder +Info: Downloding client is initializing... +Info: Installing dependent packages... +Info: * a +Info: Downloading dependent source packages... +Info: Make clean... +Info: Make build... +Info: Make install... +Info: Generatiing pkginfo.manifest... +Info: Zipping... +Info: Creating package file ... b_0.0.1_ubuntu-32.zip +Info: Checking reverse build dependency ... +Info: Uploading ... +Info: Upload succeeded. Sync local pkg-server again... +Info: Snapshot: +Info: Job is completed! +Info: Job is FINISHED successfully! +Info: Updating the source info for project "testb" diff --git a/test/build-server.multi_dist2/buildsvr.init b/test/build-server.multi_dist2/buildsvr.init new file mode 100755 index 0000000..5d4bc03 --- /dev/null +++ b/test/build-server.multi_dist2/buildsvr.init @@ -0,0 +1,50 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi + +if [ ! "$DB_PASSWD" ] ; then + read -p "Insert DB password: " input + export DB_PASSWD=$input +else + echo $DB_PASSWD +fi + +rm -rf buildsvr01 +rm -rf git01 +rm -rf bin +rm -rf ~/.build_tools/build_server/testserver3 + +../../build-svr remove -n testserver3 +mkdir buildsvr01 +cd buildsvr01 +${RUBY} ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1 +echo "DROP DATABASE testserver3;" > a +mysql -u root -p --password=$DB_PASSWD -h localhost < a +${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD +rm -f a +cd .. + +${RUBY} ../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333 +${RUBY} ../../build-svr add-dist -n testserver3 -D unstable2 -u `pwd`/pkgsvr01/unstable2 -d 127.0.0.1:3333 +${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32 +${RUBY} ../../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testa -D unstable2 -g `pwd`/git01/a -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testb -D unstable2 -g `pwd`/git01/b -b master +${RUBY} ../../build-svr add-prj -n testserver3 -N testbin -D unstable -P bin +${RUBY} ../../build-svr add-prj -n testserver3 -N testbin -D unstable2 -P bin + +mkdir -p git01 +cp ../git01/*.tar.gz git01/ +cd git01 +rm -rf a +rm -rf b +tar xf a_v1.tar.gz +tar xf b_v1.tar.gz +cd .. + +mkdir -p bin +cp ../bin/* bin/ + +${RUBY} ../../build-svr start -n testserver3 -p 2223 --CHILD diff --git a/test/build-server.multi_dist2/pkgsvr.init b/test/build-server.multi_dist2/pkgsvr.init new file mode 100755 index 0000000..adfa33b --- /dev/null +++ b/test/build-server.multi_dist2/pkgsvr.init @@ -0,0 +1,13 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi +rm -rf ~/.build_tools/pkg_server/pkgsvr01 +rm -rf `pwd`/pkgsvr01 +${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable +${RUBY} ../../pkg-svr add-dist -n pkgsvr01 -d unstable2 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable2 -o ubuntu-32 +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable2 -o windows-32 +${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333 diff --git a/test/build-server.multi_dist2/testsuite b/test/build-server.multi_dist2/testsuite new file mode 100644 index 0000000..9f25506 --- /dev/null +++ b/test/build-server.multi_dist2/testsuite @@ -0,0 +1,5 @@ +build-svr3-01.testcase +build-svr3-02.testcase +build-svr3-03.testcase +build-svr3-04.testcase +build-svr3-05.testcase diff --git a/test/git01/a.tar.gz b/test/git01/a.tar.gz new file mode 100644 index 0000000..be4b4ef Binary files /dev/null and b/test/git01/a.tar.gz differ diff --git a/test/git01/a1_v1.tar.gz b/test/git01/a1_v1.tar.gz new file mode 100644 index 0000000..b363c5a Binary files /dev/null and b/test/git01/a1_v1.tar.gz differ diff --git a/test/git01/a_new.tar.gz b/test/git01/a_new.tar.gz new file mode 100644 index 0000000..25a6ba2 Binary files /dev/null and b/test/git01/a_new.tar.gz differ diff --git a/test/git01/a_v1.tar.gz b/test/git01/a_v1.tar.gz new file mode 100644 index 0000000..049b900 Binary files /dev/null and b/test/git01/a_v1.tar.gz differ diff --git a/test/git01/a_v2.tar.gz b/test/git01/a_v2.tar.gz new file mode 100644 index 0000000..6a82258 Binary files /dev/null and b/test/git01/a_v2.tar.gz differ diff --git a/test/git01/a_v3.tar.gz b/test/git01/a_v3.tar.gz new file mode 100644 index 0000000..7915022 Binary files /dev/null and b/test/git01/a_v3.tar.gz differ diff --git a/test/git01/a_v4.tar.gz b/test/git01/a_v4.tar.gz new file mode 100644 index 0000000..25f7b3b Binary files /dev/null and b/test/git01/a_v4.tar.gz differ diff --git a/test/git01/a_v5.tar.gz b/test/git01/a_v5.tar.gz new file mode 100644 index 0000000..9b52084 Binary files /dev/null and b/test/git01/a_v5.tar.gz differ diff --git a/test/git01/b.tar.gz b/test/git01/b.tar.gz new file mode 100644 index 0000000..6d263a1 Binary files /dev/null and b/test/git01/b.tar.gz differ diff --git a/test/git01/b_new.tar.gz b/test/git01/b_new.tar.gz new file mode 100644 index 0000000..2482a1b Binary files /dev/null and b/test/git01/b_new.tar.gz differ diff --git a/test/git01/b_v1.tar.gz b/test/git01/b_v1.tar.gz new file mode 100644 index 0000000..96cb748 Binary files /dev/null and b/test/git01/b_v1.tar.gz differ diff --git a/test/git01/b_v2.tar.gz b/test/git01/b_v2.tar.gz new file mode 100644 index 0000000..42c1b1a Binary files /dev/null and b/test/git01/b_v2.tar.gz differ diff --git a/test/git01/b_v4.tar.gz b/test/git01/b_v4.tar.gz new file mode 100644 index 0000000..60ae7c1 Binary files /dev/null and b/test/git01/b_v4.tar.gz differ diff --git a/test/git01/c.tar.gz b/test/git01/c.tar.gz new file mode 100644 index 0000000..92ddfb7 Binary files /dev/null and b/test/git01/c.tar.gz differ diff --git a/test/git01/c_new.tar.gz b/test/git01/c_new.tar.gz new file mode 100644 index 0000000..10775b4 Binary files /dev/null and b/test/git01/c_new.tar.gz differ diff --git a/test/git01/c_v1.tar.gz b/test/git01/c_v1.tar.gz new file mode 100644 index 0000000..add7043 Binary files /dev/null and b/test/git01/c_v1.tar.gz differ diff --git a/test/git01/c_v1_1.tar.gz b/test/git01/c_v1_1.tar.gz new file mode 100644 index 0000000..01177c7 Binary files /dev/null and b/test/git01/c_v1_1.tar.gz differ diff --git a/test/git01/c_v2.tar.gz b/test/git01/c_v2.tar.gz new file mode 100644 index 0000000..f8d8516 Binary files /dev/null and b/test/git01/c_v2.tar.gz differ diff --git a/test/git01/c_v4.tar.gz b/test/git01/c_v4.tar.gz new file mode 100644 index 0000000..b108b4a Binary files /dev/null and b/test/git01/c_v4.tar.gz differ diff --git a/test/git01/c_v5.tar.gz b/test/git01/c_v5.tar.gz new file mode 100644 index 0000000..a682581 Binary files /dev/null and b/test/git01/c_v5.tar.gz differ diff --git a/test/git01/d.tar.gz b/test/git01/d.tar.gz new file mode 100644 index 0000000..097b1f6 Binary files /dev/null and b/test/git01/d.tar.gz differ diff --git a/test/git01/d_v0.tar.gz b/test/git01/d_v0.tar.gz new file mode 100644 index 0000000..c0a3a6e Binary files /dev/null and b/test/git01/d_v0.tar.gz differ diff --git a/test/packageserver.testsuite b/test/packageserver.testsuite new file mode 100644 index 0000000..7fe78d7 --- /dev/null +++ b/test/packageserver.testsuite @@ -0,0 +1,22 @@ +packageserver01.testcase +packageserver02.testcase +packageserver24.testcase +packageserver03.testcase +packageserver04.testcase +packageserver05.testcase +packageserver06.testcase +packageserver07.testcase +packageserver08.testcase +packageserver09.testcase +packageserver11.testcase +packageserver13.testcase +packageserver14.testcase +packageserver15.testcase +packageserver16.testcase +packageserver17.testcase +packageserver18.testcase +packageserver19.testcase +packageserver20.testcase +packageserver21.testcase +packageserver22.testcase +packageserver23.testcase diff --git a/test/packageserver01.testcase b/test/packageserver01.testcase new file mode 100644 index 0000000..f1c411e --- /dev/null +++ b/test/packageserver01.testcase @@ -0,0 +1,62 @@ +#PRE-EXEC +#EXEC +../pkg-svr -h +#POST-EXEC +#EXPECT +Package-server administer service command-line tool. + +Usage: pkg-svr [OPTS] or pkg-svr -h + +Subcommands: +create Create a package-server. +add-dist Add a distribution to package-server. +register Register a package in package-server. +remove Remove a package-server. +remove-dist Remove a distribution to package-server. +remove-snapshot Remove a snapshot in package-server. +gen-snapshot Generate a snapshot in package-server. +sync Synchronize the package-server from parent package server. +start Start the package-server. +stop Stop the package-server. +clean Delete unneeded package files in package-server. +list Show all pack + +Subcommand usage: +pkg-svr create -n -d [-u ] [-l ] +pkg-svr add-dist -n -d [-u ] [--clone] +pkg-svr add-os -n -d -o +pkg-svr register -n -d -P [--gen] [--test] +pkg-svr link -n -d --origin-pkg-name --origin-pkg-os --link-os-list +pkg-svr remove -n +pkg-svr remove-dist -n -d +pkg-svr remove-pkg -n -d -P [-o ] +pkg-svr remove-snapshot -n -d -s +pkg-svr gen-snapshot -n -d -s [-b ] +pkg-svr sync -n -d [--force] +pkg-svr clean -n -d [-s ] +pkg-svr start -n -p +pkg-svr stop -n -p +pkg-svr list [-n ] + +Options: +-n, --name package server name +-d, --dist package server distribution +-u, --url remote server url: http://127.0.0.1/dibs/unstable +-o, --os target operating system +-P, --pkgs package file path list +-s, --snapshot a snapshot name or snapshot list +-b, --base base snapshot name +-l, --loc server location +-p, --port port number + --clone clone mode + --force force update pkg file + --test upload for test + --gen generate snapshot + --origin-pkg-name + origin package name + --origin-pkg-os + origin package os + --link-os-list + target os list to link origin file +-h, --help display help +-v, --version display version diff --git a/test/packageserver02.testcase b/test/packageserver02.testcase new file mode 100644 index 0000000..408ca26 --- /dev/null +++ b/test/packageserver02.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +../pkg-svr remove -n temp_local --force +#EXEC +../pkg-svr create -n temp_local -d unstable +#POST-EXEC +#EXPECT +package server [temp_local] created successfully diff --git a/test/packageserver03.testcase b/test/packageserver03.testcase new file mode 100644 index 0000000..11eb774 --- /dev/null +++ b/test/packageserver03.testcase @@ -0,0 +1,8 @@ +#PRE-EXEC +../pkg-svr remove -n temp_remote --force +#EXEC +../pkg-svr create -n temp_remote -d unstable -u http://172.21.111.177/tmppkgsvr/tmp +#POST-EXEC +#EXPECT +snapshot is generated : +package server [temp_remote] created successfully diff --git a/test/packageserver04.testcase b/test/packageserver04.testcase new file mode 100644 index 0000000..3be6257 --- /dev/null +++ b/test/packageserver04.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +../pkg-svr remove -n temp_remote_dup --force +#EXEC +../pkg-svr create -n temp_remote_dup -d unstable -u temp_remote/unstable +#POST-EXEC +#EXPECT +package server [temp_remote_dup] created successfully diff --git a/test/packageserver05.testcase b/test/packageserver05.testcase new file mode 100644 index 0000000..da0ad18 --- /dev/null +++ b/test/packageserver05.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr add-dist -n temp_local -d stable +#POST-EXEC +#EXPECT +distribution [stable] added successfully diff --git a/test/packageserver06.testcase b/test/packageserver06.testcase new file mode 100644 index 0000000..cf49f46 --- /dev/null +++ b/test/packageserver06.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr sync -n temp_remote -d unstable +#POST-EXEC +#EXPECT +package server [temp_remote]'s distribution [unstable] has been synchronized. diff --git a/test/packageserver07.testcase b/test/packageserver07.testcase new file mode 100644 index 0000000..13bec0c --- /dev/null +++ b/test/packageserver07.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr sync -n temp_remote_dup -d unstable --force +#POST-EXEC +#EXPECT +package server [temp_remote_dup]'s distribution [unstable] has been synchronized. diff --git a/test/packageserver08.testcase b/test/packageserver08.testcase new file mode 100644 index 0000000..db9a935 --- /dev/null +++ b/test/packageserver08.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr gen-snapshot -n temp_remote -s snap01 +#POST-EXEC +#EXPECT +snapshot is generated : diff --git a/test/packageserver09.testcase b/test/packageserver09.testcase new file mode 100644 index 0000000..d8632bf --- /dev/null +++ b/test/packageserver09.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr gen-snapshot -n temp_remote -d unstable -s snap02 +#POST-EXEC +#EXPECT +snapshot is generated : diff --git a/test/packageserver10.testcase b/test/packageserver10.testcase new file mode 100644 index 0000000..7a5fcb2 --- /dev/null +++ b/test/packageserver10.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr gen-snapshot -n temp_remote -d unstable -s test +#POST-EXEC +#EXPECT +snapshot is generated : diff --git a/test/packageserver11.testcase b/test/packageserver11.testcase new file mode 100644 index 0000000..247141f --- /dev/null +++ b/test/packageserver11.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr gen-snapshot -n temp_remote -d unstable -s snap03 -b snap01 +#POST-EXEC +#EXPECT +snapshot is generated : diff --git a/test/packageserver12.testcase b/test/packageserver12.testcase new file mode 100644 index 0000000..092eb4e --- /dev/null +++ b/test/packageserver12.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr gen-snapshot -n temp_remote -d unstable -s test3 +#POST-EXEC +#EXPECT +snapshot is generated : diff --git a/test/packageserver13.testcase b/test/packageserver13.testcase new file mode 100644 index 0000000..ae8c629 --- /dev/null +++ b/test/packageserver13.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr create -n temp_remote_snap -d unstable -u temp_remote/unstable/snapshots/snap01 +#POST-EXEC +#EXPECT +package server [temp_remote_snap] created successfully diff --git a/test/packageserver14.testcase b/test/packageserver14.testcase new file mode 100644 index 0000000..06bdd06 --- /dev/null +++ b/test/packageserver14.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +cp test_server_pkg_file/smart-build-interface* ./ +#EXEC +../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen +#POST-EXEC +#EXPECT +package registed successfully diff --git a/test/packageserver15.testcase b/test/packageserver15.testcase new file mode 100644 index 0000000..af34b96 --- /dev/null +++ b/test/packageserver15.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen +#POST-EXEC +#EXPECT +existing package's version is higher than register package diff --git a/test/packageserver16.testcase b/test/packageserver16.testcase new file mode 100644 index 0000000..4d09776 --- /dev/null +++ b/test/packageserver16.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +cp test_server_pkg_file/smart-build-interface* ./ +#EXEC +../pkg-svr register -n temp_remote_dup -d unstable -P ./temp_remote/unstable/binary/smart-build-interface_1.20.1_linux.zip --gen --test +#POST-EXEC +#EXPECT +package registed successfully diff --git a/test/packageserver17.testcase b/test/packageserver17.testcase new file mode 100644 index 0000000..ad1549b --- /dev/null +++ b/test/packageserver17.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +cp test_server_pkg_file/smart-build-interface* ./ +#EXEC +../pkg-svr remove-pkg -n temp_local -d unstable -P smart-build-interface +#POST-EXEC +#EXPECT +package removed successfully diff --git a/test/packageserver18.testcase b/test/packageserver18.testcase new file mode 100644 index 0000000..431b64d --- /dev/null +++ b/test/packageserver18.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +cp test_server_pkg_file/smart-build-interface* ./ +#EXEC +../pkg-svr list +#POST-EXEC +#EXPECT +temp_remote_snap diff --git a/test/packageserver19.testcase b/test/packageserver19.testcase new file mode 100644 index 0000000..cd5b36b --- /dev/null +++ b/test/packageserver19.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +#EXEC +../pkg-svr list -n temp_local +#POST-EXEC +rm smart-build-interface_1.20.1* +#EXPECT +unstable diff --git a/test/packageserver20.testcase b/test/packageserver20.testcase new file mode 100644 index 0000000..7d47e52 --- /dev/null +++ b/test/packageserver20.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +#EXEC +../pkg-svr remove -n temp_local --force +#POST-EXEC +YES +#EXPECT +package server [temp_local] removed successfully diff --git a/test/packageserver21.testcase b/test/packageserver21.testcase new file mode 100644 index 0000000..1ae0b53 --- /dev/null +++ b/test/packageserver21.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +#EXEC +../pkg-svr remove -n temp_remote --force +#POST-EXEC +YES +#EXPECT +package server [temp_remote] removed successfully diff --git a/test/packageserver22.testcase b/test/packageserver22.testcase new file mode 100644 index 0000000..3dad192 --- /dev/null +++ b/test/packageserver22.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +#EXEC +../pkg-svr remove -n temp_remote_dup --force +#POST-EXEC +YES +#EXPECT +package server [temp_remote_dup] removed successfully diff --git a/test/packageserver23.testcase b/test/packageserver23.testcase new file mode 100644 index 0000000..6e37f2f --- /dev/null +++ b/test/packageserver23.testcase @@ -0,0 +1,7 @@ +#PRE-EXEC +#EXEC +../pkg-svr remove -n temp_remote_snap --force +#POST-EXEC +YES +#EXPECT +package server [temp_remote_snap] removed successfully diff --git a/test/packageserver24.testcase b/test/packageserver24.testcase new file mode 100644 index 0000000..2657bab --- /dev/null +++ b/test/packageserver24.testcase @@ -0,0 +1,8 @@ +#PRE-EXEC +#EXEC +../pkg-svr add-os -n temp_local -d unstable -o ubuntu-32 +#POST-EXEC +../pkg-svr add-os -n temp_local -d unstable -o windows-32 +#EXPECT +snapshot is generated : +package server add os [ubuntu-32] successfully diff --git a/test/packageserver25.testcase b/test/packageserver25.testcase new file mode 100644 index 0000000..e399ad8 --- /dev/null +++ b/test/packageserver25.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-svr link -n temp_local -d unstable --origin-pkg-name smart-build-interface --origin-pkg-os ubuntu-10.04-32 --link-os-list windows-7-32 +#POST-EXEC +#EXPECT +package linked successfully diff --git a/test/pkg-cli-checkupgrade.testcase b/test/pkg-cli-checkupgrade.testcase new file mode 100644 index 0000000..f9a19be --- /dev/null +++ b/test/pkg-cli-checkupgrade.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 +../pkg-cli check-upgrade -l pkgcli01 -u http://172.21.111.132/testserver2/unstable +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +"base-ide-product" package : 0.20.8 -> +Info: Checked packages for upgrading.. OK diff --git a/test/pkg-cli-clean-f.testcase b/test/pkg-cli-clean-f.testcase new file mode 100644 index 0000000..fd4543d --- /dev/null +++ b/test/pkg-cli-clean-f.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -t -l pkgcli01 +../pkg-cli clean -l pkgcli01 -f +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +Info: There is no any package. diff --git a/test/pkg-cli-download-t.testcase b/test/pkg-cli-download-t.testcase new file mode 100644 index 0000000..6d7263b --- /dev/null +++ b/test/pkg-cli-download-t.testcase @@ -0,0 +1,13 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli download -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -t -l pkgcli01 +ls pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product_0.20.8_linux.zip +common-eplugin_0.20.6_linux.zip +nativeapp-eplugin_0.20.4_linux.zip +nativecommon-eplugin_0.20.1_linux.zip diff --git a/test/pkg-cli-download.testcase b/test/pkg-cli-download.testcase new file mode 100644 index 0000000..f4e41d1 --- /dev/null +++ b/test/pkg-cli-download.testcase @@ -0,0 +1,10 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +cd pkgcli01; ../../pkg-cli download -p base-ide-product -u http://172.21.111.132/testserver3/unstable +ls pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product_1.0.2_linux.zip diff --git a/test/pkg-cli-install-f.testcase b/test/pkg-cli-install-f.testcase new file mode 100644 index 0000000..7794646 --- /dev/null +++ b/test/pkg-cli-install-f.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver2/unstable -l pkgcli01 +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 -f +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.8) diff --git a/test/pkg-cli-install-t.testcase b/test/pkg-cli-install-t.testcase new file mode 100644 index 0000000..00d2734 --- /dev/null +++ b/test/pkg-cli-install-t.testcase @@ -0,0 +1,13 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -t -l pkgcli01 +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.8) +common-eplugin (0.20.6) +nativeapp-eplugin (0.20.4) +nativecommon-eplugin (0.20.1) diff --git a/test/pkg-cli-install.testcase b/test/pkg-cli-install.testcase new file mode 100644 index 0000000..31ac836 --- /dev/null +++ b/test/pkg-cli-install.testcase @@ -0,0 +1,10 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.8) diff --git a/test/pkg-cli-installfile-f.testcase b/test/pkg-cli-installfile-f.testcase new file mode 100644 index 0000000..810ad2f --- /dev/null +++ b/test/pkg-cli-installfile-f.testcase @@ -0,0 +1,13 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver2/unstable -l pkgcli01 +../pkg-cli download -p base-ide-product -u http://172.21.111.132/testserver3/unstable +../pkg-cli install-file -p base-ide-product_0.20.8_linux.zip -l pkgcli01 -f +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -f base-ide-product_0.20.8_linux.zip +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.8) diff --git a/test/pkg-cli-installfile.testcase b/test/pkg-cli-installfile.testcase new file mode 100644 index 0000000..ebdb5de --- /dev/null +++ b/test/pkg-cli-installfile.testcase @@ -0,0 +1,12 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli download -p base-ide-product -u http://172.21.111.132/testserver3/unstable +../pkg-cli install-file -p base-ide-product_0.20.8_linux.zip -l pkgcli01 +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -f base-ide-product_0.20.8_linux.zip +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.8) diff --git a/test/pkg-cli-listlpkg.testcase b/test/pkg-cli-listlpkg.testcase new file mode 100644 index 0000000..31ac836 --- /dev/null +++ b/test/pkg-cli-listlpkg.testcase @@ -0,0 +1,10 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.8) diff --git a/test/pkg-cli-listrpkg.testcase b/test/pkg-cli-listrpkg.testcase new file mode 100644 index 0000000..84bf751 --- /dev/null +++ b/test/pkg-cli-listrpkg.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-cli list-rpkg -u http://172.21.111.132/testserver3/unstable +#POST-EXEC +#EXPECT +base-ide-product (1.0.2) diff --git a/test/pkg-cli-showlpkg.testcase b/test/pkg-cli-showlpkg.testcase new file mode 100644 index 0000000..dbee48c --- /dev/null +++ b/test/pkg-cli-showlpkg.testcase @@ -0,0 +1,12 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 +../pkg-cli show-lpkg -p base-ide-product -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +Package : base-ide-product +Version : 0.20.8 +OS : linux diff --git a/test/pkg-cli-showrpkg.testcase b/test/pkg-cli-showrpkg.testcase new file mode 100644 index 0000000..fc5cf62 --- /dev/null +++ b/test/pkg-cli-showrpkg.testcase @@ -0,0 +1,8 @@ +#PRE-EXEC +#EXEC +../pkg-cli show-rpkg -p base-ide-product -u http://172.21.111.132/testserver3/unstable +#POST-EXEC +#EXPECT +Package : base-ide-product +Version : 1.0.2 +OS : linux diff --git a/test/pkg-cli-source.testcase b/test/pkg-cli-source.testcase new file mode 100644 index 0000000..64053ad --- /dev/null +++ b/test/pkg-cli-source.testcase @@ -0,0 +1,10 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +cd pkgcli01; ../../pkg-cli source -p base-ide-product -u http://172.21.111.132/testserver3/unstable +ls pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +product_0.20.8.tar.gz diff --git a/test/pkg-cli-uninstall-t.testcase b/test/pkg-cli-uninstall-t.testcase new file mode 100644 index 0000000..749815f --- /dev/null +++ b/test/pkg-cli-uninstall-t.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -l pkgcli01 -t +../pkg-cli uninstall -p base-ide-product -l pkgcli01 -t +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +Info: There is no any package. diff --git a/test/pkg-cli-uninstall.testcase b/test/pkg-cli-uninstall.testcase new file mode 100644 index 0000000..10e7647 --- /dev/null +++ b/test/pkg-cli-uninstall.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product - http://172.21.111.132/testserver3/unstable -l pkgcli01 +../pkg-cli uninstall -p base-ide-product -l pkgcli01 +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +Info: There is no any package. diff --git a/test/pkg-cli-update.testcase b/test/pkg-cli-update.testcase new file mode 100644 index 0000000..3c6fa52 --- /dev/null +++ b/test/pkg-cli-update.testcase @@ -0,0 +1,6 @@ +#PRE-EXEC +#EXEC +../pkg-cli update -u http://172.21.111.132/testserver3/unstable +#POST-EXEC +#EXPECT +Update package list from "http://172.21.111.132/testserver3/unstable".. OK diff --git a/test/pkg-cli-upgrade.testcase b/test/pkg-cli-upgrade.testcase new file mode 100644 index 0000000..493d947 --- /dev/null +++ b/test/pkg-cli-upgrade.testcase @@ -0,0 +1,11 @@ +#PRE-EXEC +rm -rf pkgcli01 +mkdir pkgcli01 +#EXEC +../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 +../pkg-cli upgrade -l pkgcli01 -u http://172.21.111.132/testserver2/unstable +../pkg-cli list-lpkg -l pkgcli01 +#POST-EXEC +rm -rf pkgcli01 +#EXPECT +base-ide-product (0.20.14) diff --git a/test/pkg-cli.testsuite b/test/pkg-cli.testsuite new file mode 100644 index 0000000..21c2fe0 --- /dev/null +++ b/test/pkg-cli.testsuite @@ -0,0 +1,18 @@ +pkg-cli-update.testcase +pkg-cli-listrpkg.testcase +pkg-cli-showrpkg.testcase +pkg-cli-download.testcase +pkg-cli-download-t.testcase +pkg-cli-source.testcase +pkg-cli-install.testcase +pkg-cli-install-t.testcase +pkg-cli-install-f.testcase +pkg-cli-uninstall.testcase +pkg-cli-uninstall-t.testcase +pkg-cli-installfile.testcase +pkg-cli-installfile-f.testcase +pkg-cli-listlpkg.testcase +pkg-cli-showlpkg.testcase +pkg-cli-checkupgrade.testcase +pkg-cli-upgrade.testcase +pkg-cli-clean-f.testcase diff --git a/test/pkg-list b/test/pkg-list index cf64628..55d5272 100644 --- a/test/pkg-list +++ b/test/pkg-list @@ -1,24 +1,40 @@ -Package : A +Source : Origin Version : 0.1.0 +Maintainer : taejun.ha + +Package : A OS : linux +C-test : test Build-host-os :linux | windows | darwin -Maintainer : taejun.ha Path : binary/A_0.1.0_linux.zip +C-commic : ask Origin : remote -SHA256 : 52b400554f2a29dec46144af649181cf287c000b4feb65de72055ed9f11924a9 +C-origin : kkk +Description : this is my first +script +#Changes : kkk +#sa;ldfkj +#alsdkfj +#lsdkfj Package: B -Version : 0.2.0 OS : linux Build-host-os :linux | windows | darwin -Maintainer : taejun.ha Install-dependency : C, D, E Build-dependency : F (>= 1.0.0.20101221), E (>= 1.0.0.20101221) Source-dependency : D, scratchbox-aquila-simulator-rootstrap [ linux |windows ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17) Path : -Source : Origin -From-server? : true SHA256 : your_checksum Description : this is my first -project -descriotion +script +C-kim : oks +Change-log : +* 0.1.0 +test + ttkk +* 1.0.8 +Add change log function + pkginfo.manifest include "change log" section +* 1.0.7 +dibs document change + you can read dibs documents in ubuntu using PDF readeranges diff --git a/test/pkg-list-local b/test/pkg-list-local new file mode 100644 index 0000000..ce331b6 --- /dev/null +++ b/test/pkg-list-local @@ -0,0 +1,17 @@ +Include : pkg-list + +Package : A +OS : windows +Build-host-os :linux | windows | darwin +Path : binary/A_0.1.0_linux.zip +Origin : remote + +Package: B +OS : windows +Build-host-os :linux | windows | darwin +Install-dependency : C, D, E +Build-dependency : F (>= 1.0.0.20101221), E (>= 1.0.0.20101221) +Source-dependency : D, scratchbox-aquila-simulator-rootstrap [ linux |windows ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17) +Path : +SHA256 : your_checksum +Description : this is my first diff --git a/test/pkginfo.manifest b/test/pkginfo.manifest index ebace22..da69b2d 100644 --- a/test/pkginfo.manifest +++ b/test/pkginfo.manifest @@ -5,14 +5,17 @@ Build-host-os:linux | windows | darwin Maintainer : your_name name Install-dependency : codecoverage, rootstrap-slp-device-1.0, slp-ide Build-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221), scratchbox-aquila-simulator-rootstrap (>= 1.0.0.20101221), scratchbox-core (>= 1.0.17) -Build-src-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221) [linux|windows], scratchbox-aquila-simulator-rootstrap [ linux |windows ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17) +#Build-src-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221) [linux|windows], scratchbox-aquila-simulator-rootstrap [ linux |windows ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17) Description : this is my first +project that +is my +preciuse project : descriotion : Attribute : -Install-script : -Remove-script : -Category : +#Install-script : +#Remove-script : +#Category : Conflicts : Source : origin @@ -23,13 +26,15 @@ Build-host-os:linux | windows | darwin Maintainer : your_name name Install-dependency : codecoverage, rootstrap-slp-device-1.0, slp-ide Build-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221), scratchbox-aquila-simulator-rootstrap (>= 1.0.0.20101221), scratchbox-core (>= 1.0.17) -Build-src-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221) [linux|windows], scratchbox-aquila-simulator-rootstrap [ linux |windows ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17) +Source-dependency : scratchbox-aquila-simulator-rootstrap [ linux |windows ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17) Description : this is my first +hello +project project : descriotion : Attribute : -Install-script : -Remove-script : -Category : +C-ategory : +#Install-script : +#Remove-script : Conflicts : Source : origin diff --git a/test/pkgsvr2.init b/test/pkgsvr2.init new file mode 100755 index 0000000..e97681c --- /dev/null +++ b/test/pkgsvr2.init @@ -0,0 +1,7 @@ +#!/bin/sh +rm -rf ~/.build_tools/pkg_server/pkgsvr02 +rm -rf `pwd`/pkgsvr02 +ruby -d ../pkg-svr create -n pkgsvr02 -d unstable +ruby -d ../pkg-svr add-os -n pkgsvr02 -d unstable -o ubuntu-32 +ruby -d ../pkg-svr add-os -n pkgsvr02 -d unstable -o windows-32 +ruby -d ../pkg-svr start -n pkgsvr02 -p 4444 diff --git a/test/regression.rb b/test/regression.rb new file mode 100755 index 0000000..11aa893 --- /dev/null +++ b/test/regression.rb @@ -0,0 +1,203 @@ +#!/usr/bin/ruby +$success_cases=[] +$failure_cases=[] +$testcases=[] + +$total_cnt = 0 + +testCaseName = "" +resultCheck = "" +resultFlag = "" +resultCmdCount = 0 + + +class TestCase + attr_accessor :name, :pre_exec_cmds, :exec_cmds, :post_exec_cmds, :expected_results + def initialize(name) + @name = name + @pre_exec_cmds = [] + @exec_cmds = [] + @post_exec_cmds = [] + @expected_results = [] + end + + def is_succeeded?(results) + i = 0 + @expected_results.each do |e| + found = false + if results[i].nil? then + return false + end + if not results[i].include? e then + return false + end + i += 1 + end + + return true + end +end + + +# parse +def parse_testcase(file_name) + # create + tcase = TestCase.new( file_name ) + + # parse + File.open(file_name,"r") do |f| + status="START" + f.each_line do |l| + ln = l.strip + if ln == "#PRE-EXEC" or ln == "#EXEC" or + ln == "#POST-EXEC" or ln == "#EXPECT" then + + status = ln + else + case status + when "#PRE-EXEC" + tcase.pre_exec_cmds.push ln + when "#EXEC" + tcase.exec_cmds.push ln + when "#POST-EXEC" + tcase.post_exec_cmds.push ln + when "#EXPECT" + tcase.expected_results.push ln + else + # ignore + end + end + end + end + + return tcase +end + + +# test execution +def execute( file_name ) + printf("#{file_name} ... ") + STDOUT.flush + + # parse + tcase = parse_testcase( file_name ) + + # pre-exec + tcase.pre_exec_cmds.each do |cmd| + fork_p = false + if cmd[-1,1] == "&" then + cmd = cmd[0..-2] + fork_p = true + end + + # get result + if not fork_p then + IO.popen("#{cmd} 2>&1") { |io| + # io.each do |line| + # puts "---> #{line}" + # end + } + else + IO.popen("#{cmd} 2>&1 &") { |io| + # io.each do |line| + # puts "---> #{line}" + # end + } + end + #`#{cmd}` + end + + # exec + results = [] + tcase.exec_cmds.each do |cmd| + fork_p = false + hidden_p = false + if cmd[-1,1] == "&" then + cmd = cmd[0..-2] + fork_p = true + end + if cmd[0,1] == ">" then + cmd = cmd[1..-1] + hidden_p = true + end + # get result + if fork_p then + IO.popen("#{cmd} 2>&1 &") { |io| + io.each do |line| + if not hidden_p then + results.push line.strip + #puts "---> #{line}" + end + end + } + else + IO.popen("#{cmd} 2>&1") { |io| + io.each do |line| + if not hidden_p then + results.push line.strip + #puts "---> #{line}" + end + end + } + end + end + + # check expected result + if tcase.is_succeeded?(results) then + puts "SUCCESS" + $success_cases.push file_name + else + puts "FAIL" + $failure_cases.push file_name + results.each do |l| + puts ">" + l + end + end + + # post-exec + tcase.post_exec_cmds.each do |cmd| + # get result + IO.popen("#{cmd} 2>&1") { |io| + } + #`#{cmd}` + end +end + + +#test_list file open +if (ARGV.size() == 0) + testsuite_name = "list.txt" +else + testsuite_name = ARGV.shift +end + +# execute testsuite +puts +puts "Regression Test Start " +puts "==================================" + +File.open( testsuite_name ) do |f| + f.each_line do |line| + $testcases.push("#{line.strip}") + execute(line.strip) + end +end + +# print result +puts +puts "Regression Test Result" +puts "----------------------" +puts "Total Test Case : #{$testcases.count}" +puts "Test Success : #{$success_cases.count}" +puts "Test Errors : #{$failure_cases.count}" +puts + +if $failure_cases.count != 0 then + puts "Test Fail Files" + puts "---------------" + $failure_cases.each do |name| + puts name + end + puts +end + diff --git a/test/test.sh b/test/test.sh new file mode 100755 index 0000000..e765f43 --- /dev/null +++ b/test/test.sh @@ -0,0 +1,5 @@ +#!/bin/sh +./regression.rb pkg-cli.testsuite +./regression.rb packageserver.testsuite +./regression.rb buildserver.testsuite +./regression.rb buildcli.testsuite diff --git a/test/test_pkglist_parser.rb b/test/test_pkglist_parser.rb index c299f7f..0c11ace 100755 --- a/test/test_pkglist_parser.rb +++ b/test/test_pkglist_parser.rb @@ -2,8 +2,9 @@ require '../src/common/parser' require '../src/common/package' -alist = Parser.read_pkg_list "pkg-list" -a_list = alist.values -a_list.each do |l| +alist = Parser.read_multy_pkginfo_from "pkg-list" +alist.each do |l| l.print -end + puts l.change_log_string + puts "" +end diff --git a/test/test_server b/test/test_server index 64bdb77..c3f18a0 100755 --- a/test/test_server +++ b/test/test_server @@ -1,65 +1,66 @@ #!/bin/sh echo "============ remove 1 ==============" -../pkg-svr remove -i temp_local +../pkg-svr remove -n temp_local --force echo "============ remove 2 ==============" -../pkg-svr remove -i temp_remote +../pkg-svr remove -n temp_remote --force echo "============ remove 3 ==============" -../pkg-svr remove -i temp_remote_dup +../pkg-svr remove -n temp_remote_dup --force echo "============ remove 4 ==============" -../pkg-svr remove -i temp_remote_snap +../pkg-svr remove -n temp_remote_snap --force echo "============ create 1 ==============" -../pkg-svr create -i temp_local -d unstable +../pkg-svr create -n temp_local -d unstable echo "============ create 2 ==============" -../pkg-svr create -i temp_remote -d unstable -u http://172.21.17.55/pkgserver/unstable +../pkg-svr create -n temp_remote -d unstable -u http://172.21.17.55/private/develop echo "============ create 3 ==============" -../pkg-svr create -i temp_remote_dup -d unstable -u temp_remote/unstable +../pkg-svr create -n temp_remote_dup -d unstable -u temp_local/unstable echo "============ add dist 1 ==============" -../pkg-svr add-dist -i temp_local -d stable +../pkg-svr add-dist -n temp_local -d stable echo "============ sync 1 ==============" -../pkg-svr sync -i temp_remote -d unstable +../pkg-svr sync -n temp_remote -d unstable echo "============ sync 2 ==============" -../pkg-svr sync -i temp_remote_dup -d unstable -f +../pkg-svr sync -n temp_remote_dup -d unstable --force echo "============ gen snapshot 1 ==============" -../pkg-svr gen-snapshot -i temp_remote +../pkg-svr gen-snapshot -n temp_remote echo "============ gen snapshot 2 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable +../pkg-svr gen-snapshot -n temp_remote -d unstable echo "============ gen snapshot 3 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -n test +../pkg-svr gen-snapshot -n temp_remote -d unstable -s test echo "============ gen snapshot 4 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -n test2 -b test +../pkg-svr gen-snapshot -n temp_remote -d unstable -s test2 -b test echo "============ gen snapshot 5 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -o linux +../pkg-svr gen-snapshot -n temp_remote -d unstable -o linux echo "============ gen snapshot 6 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -o windows +../pkg-svr gen-snapshot -n temp_remote -d unstable -o windows echo "============ gen snapshot 7 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -o darwin +../pkg-svr gen-snapshot -n temp_remote -d unstable -o darwin echo "============ gen snapshot 8 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -o all +../pkg-svr gen-snapshot -n temp_remote -d unstable -o all echo "============ gen snapshot 9 ==============" -../pkg-svr gen-snapshot -i temp_remote -d unstable -o all -p test_server_pkg_file/smart-build-interface_1.20.1_linux.zip -n test3 +../pkg-svr gen-snapshot -n temp_remote -d unstable -o all -P test_server_pkg_file/smart-build-interface_1.20.1_linux.zip -s test3 echo "============ create 4 ==============" -../pkg-svr create -i temp_remote_snap -d unstable -u temp_remote/unstable/snapshots/test +../pkg-svr create -n temp_remote_snap -d unstable -u temp_remote/unstable/snapshots/test echo "============ register 1 ==============" -cp test_server_pkg_file/smart-build-interface_1.20.1_linux.zip ./smart-build-interface_1.20.1_linux.zip -cp test_server_pkg_file/smart-build-interface_1.20.1.tar.gz ./smart-build-interface_1.20.1.tar.gz -../pkg-svr register -i temp_remote -d unstable -p smart-build-interface_1.20.1_linux.zip -s smart-build-interface_1.20.1.tar.gz -g -echo "============ spkg path 1 ==============" -../pkg-svr spkg-path -i temp_remote -d unstable -s smart-build-interface_1.20.1.tar.gz +cp test_server_pkg_file/smart-build-interface_*_linux.zip ./ +../pkg-svr register -n temp_local -d unstable -P smart-build-interface_1.20.1_linux.zip echo "============ register 2 ==============" -cp test_server_pkg_file/smart-build-interface_1.20.1_linux.zip ./smart-build-interface_1.20.1_linux.zip -cp test_server_pkg_file/smart-build-interface_1.20.1.tar.gz ./smart-build-interface_1.20.1.tar.gz -../pkg-svr register -i temp_remote -d unstable -p smart-build-interface_1.20.1_linux.zip -s smart-build-interface_1.20.1.tar.gz -g +cp test_server_pkg_file/smart-build-interface_*_linux.zip ./ +../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen echo "============ register 3 ==============" -../pkg-svr register -i temp_remote_dup -d unstable -p ./temp_remote/unstable/binary/smart-build-interface_1.20.1_linux.zip -s ./temp_remote/unstable/source/smart-build-interface_1.20.1.tar.gz -g -t +cp test_server_pkg_file/smart-build-interface_*_linux.zip ./ +../pkg-svr register -n temp_remote_dup -d unstable -P smart-build-interface_1.20.1_linux.zip --gen --test +echo "============ register 4 ==============" +cp test_server_pkg_file/archive.zip ./ +../pkg-svr register -n temp_local -d unstable -A archive.zip echo "============ remove 3 ==============" -../pkg-svr remove-pkg -i temp_remote_dup -d unstable -p smart-build-interface +../pkg-svr remove-pkg -n temp_local -d unstable -P smart-build-interface +echo "============ clean 1 ==============" +../pkg-svr clean -n temp_local -d unstable +echo "============ clean 2 ==============" +../pkg-svr clean -n temp_remote -d unstable -s test,test2,test3 echo "============ list 1 ==============" ../pkg-svr list echo "============ list 2 ==============" -../pkg-svr list -i temp_local -#../pkg-svr remove -i temp +../pkg-svr list -n temp_local +#../pkg-svr remove -n temp -#cleanup -rm smart-build-interface_1.20.1_linux.zip -rm smart-build-interface_1.20.1.tar.gz diff --git a/test/test_server_pkg_file/archive.zip b/test/test_server_pkg_file/archive.zip new file mode 100644 index 0000000..140bd05 Binary files /dev/null and b/test/test_server_pkg_file/archive.zip differ diff --git a/test/test_server_pkg_file/smart-build-interface_1.20.1_linux.zip b/test/test_server_pkg_file/smart-build-interface_1.20.1_linux.zip index 109a144..cc2a217 100644 Binary files a/test/test_server_pkg_file/smart-build-interface_1.20.1_linux.zip and b/test/test_server_pkg_file/smart-build-interface_1.20.1_linux.zip differ diff --git a/test/upgrade/01.testcase b/test/upgrade/01.testcase new file mode 100644 index 0000000..af117a1 --- /dev/null +++ b/test/upgrade/01.testcase @@ -0,0 +1,9 @@ +#PRE-EXEC +./dibs1/build-svr upgrade -n testserver3 -D unstable +#EXEC +sleep 3 +ls dibs1/VERSION dibs2/VERSION +#POST-EXEC +#EXPECT +dibs1/VERSION +dibs2/VERSION diff --git a/test/upgrade/buildsvr1.init b/test/upgrade/buildsvr1.init new file mode 100755 index 0000000..0578b61 --- /dev/null +++ b/test/upgrade/buildsvr1.init @@ -0,0 +1,34 @@ +#!/bin/sh +CURDIR=`pwd` +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby " +fi + +rm -rf buildsvr01 +rm -rf git01 +rm -rf bin +rm -rf ~/.build_tools/build_server/testserver3 +rm -rf dibs1 +mkdir dibs1 +cp -r ../../src dibs1/ +cp -r ../../build-svr dibs1/ +cp -r ../../pkg-svr dibs1/ +cp -r ../../upgrade dibs1/ +cd ../../ +./pkg-build -u $CURDIR/pkgsvr01/unstable +cd $CURDIR + +dibs1/build-svr remove -n testserver3 +mkdir buildsvr01 +cd buildsvr01 +${RUBY} ../dibs1/build-svr create -n testserver3 +${RUBY} ../dibs1/build-svr migrate -n testserver3 +cd .. + +${RUBY} dibs1/build-svr add-dist -n testserver3 -D unstable -u $CURDIR/pkgsvr01/unstable -d 127.0.0.1:3333 +${RUBY} dibs1/build-svr add-svr -n testserver3 -d 127.0.0.1:2224 +${RUBY} dibs1/build-svr add-os -n testserver3 -o ubuntu-32 +${RUBY} dibs1/pkg-svr register -n pkgsvr01 -d unstable -P ../../dibs_*.zip + +${RUBY} dibs1/build-svr start -n testserver3 -p 2223 + diff --git a/test/upgrade/buildsvr2.init b/test/upgrade/buildsvr2.init new file mode 100755 index 0000000..ac5ccf7 --- /dev/null +++ b/test/upgrade/buildsvr2.init @@ -0,0 +1,22 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby " +fi + +rm -rf buildsvr02 +rm -rf dibs2 +mkdir dibs2 +cp -r ../../src dibs2/ +cp -r ../../build-svr dibs2/ +cp -r ../../pkg-svr dibs2/ +cp -r ../../upgrade dibs2/ + +../../build-svr remove -n testserver4 +mkdir buildsvr02 +cd buildsvr02 +${RUBY} ../dibs2/build-svr create -n testserver4 +${RUBY} ../dibs2/build-svr migrate -n testserver4 +cd .. +${RUBY} dibs2/build-svr add-dist -n testserver4 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333 + +${RUBY} dibs2/build-svr start -n testserver4 -p 2224 diff --git a/test/upgrade/pkgsvr.init b/test/upgrade/pkgsvr.init new file mode 100755 index 0000000..d0c7cd9 --- /dev/null +++ b/test/upgrade/pkgsvr.init @@ -0,0 +1,9 @@ +#!/bin/sh +if [ "x${RUBY}" = "x" ] ;then + RUBY="ruby -d" +fi +rm -rf ~/.build_tools/pkg_server/pkgsvr01 +rm -rf `pwd`/pkgsvr01 +${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable +${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32 +${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333 diff --git a/test/upgrade/testsuite b/test/upgrade/testsuite new file mode 100644 index 0000000..1bb2eb2 --- /dev/null +++ b/test/upgrade/testsuite @@ -0,0 +1 @@ +01.testcase diff --git a/tizen-ide/get_ide_sources.sh b/tizen-ide/get_ide_sources.sh new file mode 100755 index 0000000..b7c58d9 --- /dev/null +++ b/tizen-ide/get_ide_sources.sh @@ -0,0 +1,276 @@ +#!/bin/bash + +############################################################### +## Variables +############################################################### + +START_PATH=~+ ## like `pwd` +SCRIPT_NAME=$0 +SCRIPT_OPERATION=$1 +ARG1=$2 +ARG2=$3 +ARG3=$4 +GIT_PORT=29419 +CONTINUE=n +GIT_LIST=" +/sdk/ide/common-eplugin +/sdk/ide/eventinjector-eplugin +/sdk/ide/nativecommon-eplugin +/sdk/ide/nativeappcommon-eplugin +/sdk/ide/native-eplugin +/sdk/ide/native-ext-eplugin +/sdk/ide/native-sample +/sdk/ide/nativeplatform-eplugin +/sdk/ide/unittest-eplugin +/sdk/ide/profiler-eplugin +/sdk/ide/codecoverage-eplugin +/sdk/ide/assignmenttracing-eplugin +/sdk/ide/webapp-eplugin +/sdk/ide/product +/sdk/ide/websimulator-eplugin +/sdk/tools/sdb +" +# /sdk/ide/nativeapp-eplugin +# /sdk/ide/native-gui-builder-eplugin +# /sdk/gui-builder/native-gui-builder +# /sdk/ide/telephony-eplugin +# /sdk/ide/codehiding-eplugin + +############################################################### +## Usage output functions +############################################################### + +function usage() { + echo "Usage : ${SCRIPT_NAME##*/} []"; echo + echo "The most commonly used script commands are :" + echo " clone Clone git sources about Tizen SDK" + echo " pull Pull git sources about Tizen SDK" + echo " checkout checkout git sources about Tizen SDK"; echo + exit 1 +} + +function usage_pull() { + echo "Usage : ${SCRIPT_NAME##*/} pull : Git pull in current directory"; + echo "Usage : ${SCRIPT_NAME##*/} pull : Git pull in source directory"; + + draw_line + echo " Ex1) \$ ${SCRIPT_NAME} pull"; echo + echo " Ex2) \$ ${SCRIPT_NAME} pull $(pwd)/tizen-ide-sources"; echo + exit 1 +} + +function usage_checkout() { + echo "Usage : ${SCRIPT_NAME##*/} checkout : Git checkout in current directory"; + echo "Usage : ${SCRIPT_NAME##*/} checkout : Git checkout in source directory"; + + draw_line + echo " Ex1) \$ ${SCRIPT_NAME} checkout develop"; echo + echo " Ex2) \$ ${SCRIPT_NAME} checkout develop $(pwd)/tizen-ide-sources"; echo + exit 1 +} + +function usage_clone() { + draw_line + echo "Usage : 1) ${SCRIPT_NAME##*/} clone : Git clone in curreut directory"; echo + echo " 2) ${SCRIPT_NAME##*/} clone : Git clone in destination directory" + draw_line + echo " Ex1) \$ ${SCRIPT_NAME} clone develop gerrithost" + echo " Ex2) \$ ${SCRIPT_NAME} clone release http://develop.tizen.org/git:2039 /home/usr/work/git" + exit 1 +} + + +############################################################### +## Processing Functions +############################################################### + +function draw_line() { + echo; echo "==========================================================================="; echo; +} + +## Error Check Function +function isError() { + ERROR_CODE=$? + + if [ ${ERROR_CODE} == 0 ]; then + echo "[ $1 : Done ]"; + else + echo "[ $1 : Fail (ErrorCode : ${ERROR_CODE}) ]" + if [ ${CONTINUE} == "n" ]; then + input=0 + while [ ${input} != "y" -a ${input} != "n" -a ${input} != "a" ]; do + echo "Continue? y: Yes, n: No, a: Yes to all" + read input + if [ ${input} == "n" ]; then + exit ${ERROR_CODE} + elif [ ${input} == "a" ]; then + CONTINUE=y + echo ${CONTINUE} + fi + done + fi + fi +} + +## Cloning git +function git_clone() { + GIT_PATH=$1 + GIT_NAME=${GIT_PATH##*/} + + ## ARG1 : + ## ARG2 : + ## ARG3 : + git clone -b ${ARG1} ${ARG2}:${GIT_PATH} ${ARG3}/${GIT_NAME} + isError "Cloned ${GIT_NAME}" + scp -p -P ${GIT_PORT} ${ARG2}:hooks/commit-msg ${ARG3}/${GIT_NAME}/.git/hooks/ + isError "Generate change-id ${GIT_NAME}" +} + +## Cloning git all +function git_clone_all() { + draw_line; echo "Git clone sources"; draw_line + + for GIT_EACH in ${GIT_LIST} + do + git_clone ${GIT_EACH} + done +} + +## Pulling git +function git_pull() { + GIT_PATH=$1 + GIT_NAME=${GIT_PATH##*/} + + ## ARG1 : + cd ${ARG1}/${GIT_NAME} + isError "Found git directory ( ${ARG1}/${GIT_NAME} )" + git pull + isError "Pulled ${GIT_NAME}" +} + +## Pulling git all +function git_pull_all() { + draw_line; echo "Git pull sources"; draw_line + + cd ${ARG1} + isError "Checked source directory ( ${ARG1} )" + + for GIT_EACH in ${GIT_LIST} + do + git_pull ${GIT_EACH} + done + + cd ${START_PATH} +} + +## Checking out git +function git_checkout() { + GIT_PATH=$1 + GIT_NAME=${GIT_PATH##*/} + + ## ARG1 : + cd ${ARG2}/${GIT_NAME} + isError "Found git directory ( ${ARG2}/${GIT_NAME} )" + git checkout ${ARG1} + isError "Checkout ${GIT_NAME}" +} + +## Checking out git all +function git_checkout_all() { + draw_line; echo "Git checkout"; draw_line + + cd ${ARG2} + isError "Checked source directory ( ${ARG1} )" + + for GIT_EACH in ${GIT_LIST} + do + git_checkout ${GIT_EACH} + done + + cd ${START_PATH} +} + +## Command git +function git_command() { + GIT_PATH=$1 + GIT_NAME=${GIT_PATH##*/} + + ## ARG1 : + cd ${ARG1}/${GIT_NAME} + isError "Found git directory ( ${ARG1}/${GIT_NAME} )" + git ${SCRIPT_OPERATION} + isError "Pulled ${GIT_NAME}" +} + +## Command git all +function git_command_all() { + draw_line; echo "Git ${SCRIPT_OPERATION}"; draw_line + + cd ${ARG1} + isError "Checked source directory ( ${ARG1} )" + + for GIT_EACH in ${GIT_LIST} + do + git_command ${GIT_EACH} + done + + cd ${START_PATH} +} + +############################################################### +## Begin script +############################################################### + +case ${SCRIPT_OPERATION} in + ## process "clone" operation + clone) + if [ "$#" == 4 ]; then + git_clone_all + elif [ "$#" == 3 ]; then + ARG3=$(pwd) + git_clone_all + else + usage_clone + fi + ;; + + ## process "pull" operation + pull) + if [ "$#" == 2 ]; then + git_pull_all + elif [ "$#" == 1 ]; then + ARG1=$(pwd) + git_pull_all + else + usage_pull + fi + ;; + + ## process "checkout" operation + checkout) + if [ "$#" == 3 ]; then + git_checkout_all + elif [ "$#" == 2 ]; then + ARG2=$(pwd) + git_checkout_all + else + usage_checkout + fi + ;; + + ## process default + *) + if [ "$#" == 1 ]; then + ARG1=$(pwd) + git_command_all + else + usage + fi + ;; +esac + +echo "[ Finished process ]" + +############################################################### +## End script +############################################################### diff --git a/upgrade b/upgrade new file mode 100755 index 0000000..26120ad --- /dev/null +++ b/upgrade @@ -0,0 +1,285 @@ +#!/usr/bin/ruby +=begin + + upgrade + +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: +Taejun Ha +Jiil Hyoun +Donghyuk Yang +DongHee Yang +Sungmin Kim + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Contributors: +- S-Core Co., Ltd +=end + +require 'fileutils' +require 'optparse' +$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common" +$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/build_server" +$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/pkg_server" +require "BuildServerController" +require "utils.rb" +require "log.rb" +require "client" + +def option_error_check( options ) + if options[:start] then + if options[:locate].nil? or options[:type].nil? or options[:name].nil? then + raise ArgumentError, "upgrade -l -S -t -n -p -D " + "\n" + end + else + if options[:locate].nil? or options[:url].nil? then + raise ArgumentError, "upgrade -u [-l ]" + "\n" + end + end +end + +def option_parse + options = {} + banner = "DIBS upgrade service command-line tool." + "\n" \ + + "\n" + "Usage: upgrade -u [-l ]" + "\n" \ + + "\n" + "Options:" + "\n" + + optparse = OptionParser.new(nil, 32, ' '*8) do|opts| + opts.banner = banner + + options[:locate] = File.dirname(__FILE__) + opts.on( '-l', '--locate ', 'located dibs path' ) do|locate| + options[:locate] = locate + end + + opts.on( '-u', '--url ', 'package server url: http://127.0.0.1/dibs/unstable' ) do|url| + options[:url] = url + end + + opts.on( '-I', '--install', 'install, internal option' ) do + options[:install] = true + end + + opts.on( '-S', '--start', 'start server option' ) do + options[:start] = true + end + + opts.on( '-t', '--type ', 'sever type : BUILDSERVER or PACKAGESERVER' ) do|type| + options[:type] = type + end + + opts.on( '-n', '--name ', 'build server name or package server name' ) do|name| + options[:name] = name + end + + opts.on( '-D', '--distribution ', 'build server distribution name' ) do|dist| + options[:dist] = dist + end + + options[:port] = 2222 + opts.on( '-p', '--port ', 'server port number: 2224' ) do|port| + options[:port] = port.strip.to_i + end + + opts.on( '-h', '--help', 'display this information' ) do + puts opts.banner + puts " -l, --locate , located dibs path" + puts " -u, --url , package server url: http://127.0.0.1/dibs/unstable" + exit + end + end + + optparse.parse! + + option_error_check options + + return options +end + +#option parsing +begin + option = option_parse +rescue => e + puts e.message + exit 0 +end + +# Upgrade DIBS +begin + install_opt = option[:install] + sub_cmd = option[:sub_cmd] + dibs_path = option[:locate] + pkg_svr_url= option[:url] + start_opt = option[:start] + svr_type = option[:type] + svr_name = option[:name] + svr_port = option[:port] + svr_dist = option[:dist] + + DIBS_PKG_NAME = "dibs" + BACKUP_ROOT = Utils::HOME + "/.build_tools/backup" + PREV_VER_PATH = BACKUP_ROOT + "/prev_ver" + NEW_VER_PATH = BACKUP_ROOT + "/new_ver" + UPGRADE_CMD = "#{PREV_VER_PATH}/upgrade" + BUILD_CONFIG_ROOT = "#{Utils::HOME}/.build_tools/build_server/#{svr_name}" + + if not svr_dist.nil? then + build_server = BuildServerController.get_server(svr_name) + dist = build_server.distmgr.get_distribution(svr_dist) + if dist.nil? then + log.error "Upgrade failed : No distribution name \"#{svr_dist}\" exist!", Log::LV_USER + cmd = Utils.generate_shell_command("#{dibs_path}/build-svr start -n #{svr_name} -p #{svr_port}") + Utils.spawn(cmd) + exit 1 + end + end + + if not File.exist? BACKUP_ROOT then FileUtils.mkdir_p(BACKUP_ROOT) end + log = StandardOutLog.new( "#{BUILD_CONFIG_ROOT}/log" ) + + if not install_opt then + puts "" + log.info("Upgrade Start...", Log::LV_USER) + + # Backup current dibs + if File.exist? PREV_VER_PATH then FileUtils.rm_rf(PREV_VER_PATH) end + if File.exist? NEW_VER_PATH then FileUtils.rm_rf(NEW_VER_PATH) end + FileUtils.mkdir_p(PREV_VER_PATH) + FileUtils.mkdir_p(NEW_VER_PATH) + FileUtils.cp_r("#{dibs_path}/.", PREV_VER_PATH, :preserve => true) + log.info("Backup DIBS [#{dibs_path}] -> [#{PREV_VER_PATH}]", Log::LV_USER) + + # Run Upgrade + if start_opt and svr_type.eql? "BUILDSERVER" then + cmd = "#{UPGRADE_CMD} -I -l #{dibs_path} -S -t #{svr_type} -n #{svr_name} -p #{svr_port}" + + if not (pkg_svr_url.nil? or pkg_svr_url.empty?) then + cmd += " -u #{pkg_svr_url}" + end + + if not (svr_dist.nil? or svr_dist.empty?) then + cmd += " -D #{svr_dist}" + end + + else + cmd = "#{UPGRADE_CMD} -I -l #{dibs_path} -u #{pkg_svr_url}" + end + + cmd = Utils.generate_shell_command(cmd) + Utils.spawn(cmd) + + else + # Get SERVER INFORMATION + if start_opt and svr_type.eql? "BUILDSERVER" then + # only when acesss build server controller + build_server = BuildServerController.get_server(svr_name) + if pkg_svr_url.nil? or pkg_svr_url.empty? then + if svr_dist.nil? or svr_dist.empty? then + pkg_svr_url = build_server.distmgr.get_default_pkgsvr_url() + else + dist = build_server.distmgr.get_distribution(svr_dist) + if not dist.nil? then + pkg_svr_url = dist.pkgsvr_url + else + log.error "Upgrade failed : No distribution name \"#{svr_dist}\" exist!", Log::LV_USER + exit 1 + end + end + end + log.info("Build server : [#{svr_name}][#{svr_port}]", Log::LV_USER) + end + log.info("Package Server : [#{pkg_svr_url}]", Log::LV_USER) + log.info("DIBS Path : [#{dibs_path}]", Log::LV_USER) + + # Download DIBS Package + client = Client.new( pkg_svr_url, NEW_VER_PATH, log) + client.update() + client.install( DIBS_PKG_NAME, Utils::HOST_OS, true, true) + + # Copy Current path + if File.exist? "#{dibs_path}" then + FileUtils.rm_rf("#{dibs_path}") + #FileUtils.mkdir_p("#{dibs_path}") + end + if File.exist? "#{NEW_VER_PATH}/tools/dibs" then + FileUtils.cp_r("#{NEW_VER_PATH}/tools/dibs/.", "#{dibs_path}", :preserve => true) + else + log.error("Not installed package error.", Log::LV_USER) + exit(1) + end + + # Execute start command + if start_opt + if not build_server.nil? and svr_type.eql? "BUILDSERVER" then + # get friends server information + build_server.get_remote_servers().each do |svr| + ip = svr.ip + port = svr.port + + build_client = BuildCommClient.create( ip, port ) + if build_client.nil? then + log.info("Friend Server #{ip}:#{port} is not running!", Log::LV_USER) + next + end + + # send request + log.info("Upgrading Friend Server #{ip}:#{port}...", Log::LV_USER) + if build_client.send "UPGRADE|#{build_server.password}" then + # recevie & print + mismatched = false + result = build_client.read_lines do |l| + log.info(l, Log::LV_USER) + if l.include? "Password mismatched!" then + mismatched = true + end + end + if not result then + log.info("Upgrading failed! #{build_client.get_error_msg()}", Log::LV_USER) + elsif mismatched then + log.info("Upgrading failed! Password mismatched!", Log::LV_USER) + end + else + log.info("Upgrading failed! #{build_client.get_error_msg()}", Log::LV_USER) + next + end + + # terminate + build_client.terminate + end + + # Start Build server + cmd = Utils.generate_shell_command("#{dibs_path}/build-svr start -n #{svr_name} -p #{svr_port}") + Utils.spawn(cmd) + + log.info("Upgrade Complete", Log::LV_USER) + log.info("Start Build server [#{cmd}]", Log::LV_USER) + + else # PACKAGE SERVER + # Start Build server + cmd = Utils.generate_shell_command("#{dibs_path}/pkg-svr start -n #{svr_name} -p #{svr_port}") + Utils.spawn(cmd) + + log.info("Upgrade Complete", Log::LV_USER) + log.info("Start Package server [#{cmd}]", Log::LV_USER) + end + else + log.info("Upgrade Complete", Log::LV_USER) + end + end +rescue => e + log.error(e.message, Log::LV_USER) + #puts e.message +end +