Update Tizen 2.0 SDK source code 2.0alpha master 2.0_alpha submit/master/20120921.081105
authordonghee <donghee.yang@samsung.com>
Tue, 18 Sep 2012 08:05:19 +0000 (17:05 +0900)
committerdonghee <donghee.yang@samsung.com>
Tue, 18 Sep 2012 08:05:19 +0000 (17:05 +0900)
Change-Id: I8625ecad315e7cb9a07e52cfff0bc594eda4f4f0

199 files changed:
README
build-cli
build-svr
doc/DIBS_Advanced_Guide.pdf [new file with mode: 0644]
doc/Tizen_SDK_Development_Guide.pdf [new file with mode: 0644]
doc/Tizen_SDK_Package_Guide.pdf [new file with mode: 0644]
package/build.linux
package/build.macos [new file with mode: 0644]
package/build.windows [new file with mode: 0644]
package/pkginfo.manifest
package/pkginfo.manifest.local [new file with mode: 0644]
pkg-build
pkg-clean
pkg-cli
pkg-svr
src/build_server/BinaryUploadProject.rb [new file with mode: 0644]
src/build_server/BuildClientOptionParser.rb
src/build_server/BuildComm.rb
src/build_server/BuildJob.rb
src/build_server/BuildServer.rb
src/build_server/BuildServerController.rb
src/build_server/BuildServerOptionParser.rb
src/build_server/CommonProject.rb [new file with mode: 0644]
src/build_server/FullBuildJob.rb [new file with mode: 0644]
src/build_server/GitBuildJob.rb
src/build_server/GitBuildProject.rb [new file with mode: 0644]
src/build_server/JobClean.rb [new file with mode: 0644]
src/build_server/JobLog.rb
src/build_server/JobManager.rb
src/build_server/LocalBuildJob.rb [deleted file]
src/build_server/MultiBuildJob.rb [new file with mode: 0644]
src/build_server/PackageSync.rb [new file with mode: 0644]
src/build_server/ProjectManager.rb [new file with mode: 0644]
src/build_server/RegisterPackageJob.rb [new file with mode: 0644]
src/build_server/RemoteBuildJob.rb
src/build_server/RemoteBuildServer.rb
src/build_server/RemoteBuilder.rb [new file with mode: 0644]
src/build_server/ReverseBuildChecker.rb [new file with mode: 0644]
src/build_server/SocketJobRequestListener.rb
src/builder/Builder.rb
src/builder/CleanOptionParser.rb
src/builder/optionparser.rb
src/common/Action.rb [new file with mode: 0644]
src/common/PackageManifest.rb
src/common/ScheduledActionHandler.rb [new file with mode: 0644]
src/common/Version.rb
src/common/fileTransfer.rb [new file with mode: 0644]
src/common/log.rb
src/common/package.rb
src/common/parser.rb
src/common/utils.rb
src/pkg_server/DistSync.rb [new file with mode: 0644]
src/pkg_server/SocketRegisterListener.rb [new file with mode: 0644]
src/pkg_server/client.rb
src/pkg_server/clientOptParser.rb
src/pkg_server/distribution.rb
src/pkg_server/downloader.rb
src/pkg_server/installer.rb
src/pkg_server/packageServer.rb
src/pkg_server/packageServerConfig.rb
src/pkg_server/serverOptParser.rb
test/a/a [deleted file]
test/a/package/build.linux [deleted file]
test/a/package/pkginfo.manifest [deleted file]
test/b/b [deleted file]
test/b/package/build.linux [deleted file]
test/b/package/pkginfo.manifest [deleted file]
test/bin/bin_0.0.0_linux.zip [new file with mode: 0644]
test/bin/bin_0.0.0_ubuntu-32.zip [new file with mode: 0644]
test/bin/bin_0.0.1_linux.zip [new file with mode: 0644]
test/bin/bin_0.0.1_ubuntu-32.zip [new file with mode: 0644]
test/bin/src.tar.gz [new file with mode: 0644]
test/build-cli-01.testcase
test/build-cli-02.testcase
test/build-cli-03.testcase
test/build-cli-03_1.testcase [new file with mode: 0644]
test/build-cli-04.testcase [new file with mode: 0644]
test/build-cli-05.testcase [new file with mode: 0644]
test/build-cli-06.testcase [new file with mode: 0644]
test/build-cli-07.testcase [new file with mode: 0644]
test/build-cli-08.testcase [new file with mode: 0644]
test/build-cli-09.testcase [new file with mode: 0644]
test/build-cli-10.testcase [new file with mode: 0644]
test/build-cli-11.testcase [new file with mode: 0644]
test/build-cli-12.testcase [new file with mode: 0644]
test/build-cli-12_1.testcase [new file with mode: 0644]
test/build-cli-13.testcase [new file with mode: 0644]
test/build-cli-14.testcase [new file with mode: 0644]
test/build-cli-15.testcase [new file with mode: 0644]
test/build-cli-16.testcase [new file with mode: 0644]
test/build-cli-17.testcase [new file with mode: 0644]
test/build-cli-18.testcase [new file with mode: 0644]
test/build-cli-19.testcase [new file with mode: 0644]
test/build-cli-20.testcase [new file with mode: 0644]
test/build-cli-21.testcase [new file with mode: 0644]
test/build-cli-22.testcase [new file with mode: 0644]
test/build-cli-23.testcase [new file with mode: 0644]
test/build-cli-24.testcase [new file with mode: 0644]
test/build-cli-25.testcase [new file with mode: 0644]
test/build-cli-26.testcase [new file with mode: 0644]
test/build-cli-27.testcase [new file with mode: 0644]
test/build-cli-28.testcase [new file with mode: 0644]
test/build-cli-29.testcase [new file with mode: 0644]
test/build-svr-01.testcase [new file with mode: 0644]
test/build-svr-02.testcase [new file with mode: 0644]
test/build-svr-03.testcase [new file with mode: 0644]
test/build-svr-04.testcase [new file with mode: 0644]
test/build-svr-05.testcase [new file with mode: 0644]
test/build-svr-06.testcase [new file with mode: 0644]
test/build-svr-07.testcase [new file with mode: 0644]
test/build-svr-08.testcase [new file with mode: 0644]
test/build-svr-09.testcase [new file with mode: 0644]
test/build-svr-10.testcase [new file with mode: 0644]
test/build-svr-11.testcase [new file with mode: 0644]
test/build-svr-12.testcase [new file with mode: 0644]
test/build-svr-13.testcase [new file with mode: 0644]
test/build-svr-14.testcase [new file with mode: 0644]
test/build-svr-15.testcase [new file with mode: 0644]
test/build-svr-16.testcase [new file with mode: 0644]
test/build-svr-17.testcase [new file with mode: 0644]
test/build-svr-18.testcase [new file with mode: 0644]
test/build-svr-19.testcase [new file with mode: 0644]
test/build-svr-20.testcase [new file with mode: 0644]
test/buildcli.testsuite
test/buildserver.testsuite
test/buildserver01.testcase [deleted file]
test/buildserver02.testcase [deleted file]
test/buildserver03.testcase [deleted file]
test/buildserver04.testcase [deleted file]
test/buildserver05.testcase [deleted file]
test/buildserver06.testcase [deleted file]
test/buildsvr.init [new file with mode: 0644]
test/c/c [deleted file]
test/c/package/build.linux [deleted file]
test/c/package/pkginfo.manifest [deleted file]
test/git01/a.tar.gz [new file with mode: 0644]
test/git01/a1_v1.tar.gz [new file with mode: 0644]
test/git01/a_new.tar.gz [new file with mode: 0644]
test/git01/a_v1.tar.gz [new file with mode: 0644]
test/git01/a_v2.tar.gz [new file with mode: 0644]
test/git01/a_v3.tar.gz [new file with mode: 0644]
test/git01/a_v4.tar.gz [new file with mode: 0644]
test/git01/a_v5.tar.gz [new file with mode: 0644]
test/git01/b.tar.gz [new file with mode: 0644]
test/git01/b_new.tar.gz [new file with mode: 0644]
test/git01/b_v1.tar.gz [new file with mode: 0644]
test/git01/b_v2.tar.gz [new file with mode: 0644]
test/git01/b_v4.tar.gz [new file with mode: 0644]
test/git01/c.tar.gz [new file with mode: 0644]
test/git01/c_new.tar.gz [new file with mode: 0644]
test/git01/c_v1.tar.gz [new file with mode: 0644]
test/git01/c_v1_1.tar.gz [new file with mode: 0644]
test/git01/c_v2.tar.gz [new file with mode: 0644]
test/git01/c_v4.tar.gz [new file with mode: 0644]
test/git01/c_v5.tar.gz [new file with mode: 0644]
test/git01/d.tar.gz [new file with mode: 0644]
test/git01/d_v0.tar.gz [new file with mode: 0644]
test/packageserver.testsuite
test/packageserver01.testcase
test/packageserver02.testcase
test/packageserver03.testcase
test/packageserver04.testcase
test/packageserver05.testcase
test/packageserver06.testcase
test/packageserver07.testcase
test/packageserver08.testcase
test/packageserver09.testcase
test/packageserver10.testcase
test/packageserver11.testcase
test/packageserver12.testcase
test/packageserver13.testcase
test/packageserver14.testcase
test/packageserver15.testcase
test/packageserver16.testcase
test/packageserver17.testcase
test/packageserver19.testcase
test/packageserver20.testcase
test/packageserver21.testcase
test/packageserver22.testcase
test/packageserver23.testcase
test/packageserver24.testcase [new file with mode: 0644]
test/packageserver25.testcase [new file with mode: 0644]
test/pkg-cli-download.testcase
test/pkg-cli-listrpkg.testcase
test/pkg-cli-showrpkg.testcase
test/pkg-list
test/pkg-list-local [new file with mode: 0644]
test/pkgsvr.init [new file with mode: 0644]
test/pkgsvr2.init [new file with mode: 0644]
test/regression.rb
test/test_bserver2c.rb [deleted file]
test/test_bserver3c.rb [deleted file]
test/test_pkglist_parser.rb
test/test_server
test/test_server_pkg_file/archive.zip [new file with mode: 0644]
test/test_server_pkg_file/smart-build-interface_1.20.1.tar.gz [deleted file]
test/test_server_pkg_file/smart-build-interface_1.20.1_linux.zip
tizen-ide/get_ide_sources.sh
upgrade [new file with mode: 0644]

diff --git a/README b/README
index e54ec3f518867dd91021f1d6a69cc6a5adab53ce..f373da2cbc1332e56f58eccfd053eceb24a19b55 100644 (file)
--- 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 <package server url>] [-o <os>] [-c <clean>] [-r <reverse build dependency check>]
     ## -u : Package server URL which contains binary and development packages.
     ##      If ommited, it will use previous server URL.
     ## pkg-build [-u <package server url>] [-o <os>] [-c <clean>] [-r <reverse build dependency check>]
     ## -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
     ## -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 <os>] [-u <package server url>] 
 You can list up available packages of server.
 
     ## pkg-cli list-rpkg [-o <os>] [-u <package server url>] 
-    ## -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.
 
     ## -u : Package server URL which contains binary and development packages.
     ##      If ommited, it will use previous server URL.
 
index 4bec1723d6ed54ee8d912a49e8eb99fbe3397fc6..820759847b0adab270e4798445d9bb3dcc99d3e5 100755 (executable)
--- a/build-cli
+++ b/build-cli
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby -d
+#!/usr/bin/ruby
 
 =begin
  
 
 =begin
  
@@ -36,75 +36,370 @@ require "utils"
 require "BuildClientOptionParser"
 require "BuildComm"
 
 require "BuildClientOptionParser"
 require "BuildComm"
 
+
+
 #option parsing 
 #option parsing 
-option = option_parse
+begin
+    option = option_parse
+rescue => e
+    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
+
+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()
+       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
+
+
+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\n",tok[1],type)
+       end
+end
 
 
-# if "--os" is not specified, use host os type
+
+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[3].nil? then
+                       puts "#{tok[1]} #{tok[0]} #{tok[2]}"
+               else
+                       puts "#{tok[1]} #{tok[0]} #{tok[2]} (#{tok[3]})"
+               end
+       end
+end
+
+
+# if "--os" is not specified, use pe
 if option[:os].nil? then 
 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[:os] = "default"
 end
 
 if option[:domain].nil? then
 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
 
        option[:domain] = "127.0.0.1"
 end
 
-if option[:port].nil? then
-       option[:port] = 2222
-end
-
 begin
        case option[:cmd] 
        when "build" 
 begin
        case option[:cmd] 
        when "build" 
-               client = BuildCommClient.create( option[:domain], option[:port])
+        result = Utils.parse_server_addr(option[:domain])
+        if result.nil? then
+            puts "Server address is incorrect. (#{option[:domain]})"
+            puts "Tune as following format."
+            puts " <ip>:<port>"
+            exit 1
+        end
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
                if not client.nil? then
                if not client.nil? then
-                       client.send "BUILD,GIT,#{option[:git]},#{option[:commit]},#{option[:os]},,#{option[:async]}"
+                       client.send "BUILD|GIT|#{option[:project]}|#{option[:passwd]}|#{option[:os]}|#{option[:async]}|#{option[:noreverse]}"
                        client.print_stream
                        client.terminate
                        client.print_stream
                        client.terminate
+               else
+                       puts "Connection to server failed!"
+                       exit 1
                end
        when "resolve"
                end
        when "resolve"
-               client = BuildCommClient.create( option[:domain], option[:port])
+        result = Utils.parse_server_addr(option[:domain])
+        if result.nil? then
+            puts "Server address is incorrect. (#{option[:domain]})"
+            puts "Tune as following format."
+            puts " <ip>:<port>"
+            exit 1
+        end
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
                if not client.nil? then
                if not client.nil? then
-                       client.send "RESOLVE,GIT,#{option[:git]},#{option[:commit]},#{option[:os]},,#{option[:async]}" 
+                       client.send "RESOLVE|GIT|#{option[:project]}|#{option[:passwd]}|#{option[:os]}|#{option[:async]}" 
                        client.print_stream
                        client.terminate
                end
        when "query"
                        client.print_stream
                        client.terminate
                end
        when "query"
-               # SYSTEM INFO
-               client = BuildCommClient.create( option[:domain], option[:port])
-               if not client.nil? then
-                       client.send "QUERY,SYSTEM" 
-                       result0 = client.receive_data()
-                       if result0.nil? then
-                               client.terminate
-                               exit(-1)
+        result = Utils.parse_server_addr(option[:domain])
+        if result.nil? then
+            puts "Server address is incorrect. (#{option[:domain]})"
+            puts "Tune as following format."
+            puts " <ip>:<port>"
+            exit 1
+        end
+
+               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 " <ip>:<port>"
+            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 " <ip>:<port>"
+            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 " <ip>:<port>"
+            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 " <ip>:<port>"
+            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]}"
+                               result1 = client.receive_data()
+                               if result1.nil? then
+                                       client.terminate
+                                       exit(-1)
+                               end
+                               puts result1
+                       else
+                               puts "Connection to server failed!"
+                               exit 1
                        end
                        end
-                       result0 = result0[0].split(",").map { |x| x.strip }
-                       puts "HOST-OS: #{result0[0]}"
-                       puts "MAX_WORKING_JOBS: #{result0[1]}"
+               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 " <ip>:<port>"
+            exit 1
+        end
+               bs_ip = result[0]
+               bs_port = result[1]
+
+        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://<usrename>:<passwd>@<address>"
+            exit 1
+        end
+               ip = ftp_result[0]
+        port = ftp_result[1]
+               username = ftp_result[2]
+               passwd = ftp_result[3]
+
+               # 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(ip, port, username, passwd, option[:package])
+               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}")
+               client.print_stream
+               client.terminate
+
+       # for test
+       when "upload"
+               # check file exist 
+               if not File.exist? option[:file] then
+                       puts "The file does not exist!.. #{option[:file]}"
+                       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 " <ip>:<port>"
+            exit 1
+        end
+
+               # FTP INFO
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
+               if client.nil? then
+                       puts "Can't access server #{result[0]}:#{result[1]}"
+                       exit(-1)
+               end
+               client.send "QUERY|FTP"
+               result0 = client.receive_data()
+               if result0.nil? then
                        client.terminate
                        client.terminate
+                       exit(-1)
                end
                end
+               result0 = result0[0].split(",").map { |x| x.strip }
+               ip = result0[0]
+               username = result0[1]
+               passwd = result0[2]
+               client.terminate
 
 
-               # 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)
-                       end
-                       puts "* JOB *"
-                       for item in result1
-                               tok = item.split(",").map { |x| x.strip }
-                               puts "#{tok[1]} #{tok[0]} #{tok[2]}"    
-                       end
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
+               if client.nil? then
+                       puts "Can't access server #{result[0]}:#{result[1]}"
+                       exit(-1)
+               end
+               client.send("UPLOAD")
+               result = client.send_file(ip, username, passwd, option[:file])
+               client.terminate
+               if not result then
+                       puts "Uploading file failed!.. #{option[:file]}"
+                       exit(-1)
+               else
+                       puts "Uploading file succeeded!"
+               end
+       
+       when "download"
+        result = Utils.parse_server_addr(option[:domain])
+        if result.nil? then
+            puts "Server address is incorrect. (#{option[:domain]})"
+            puts "Tune as following format."
+            puts " <ip>:<port>"
+            exit 1
+        end
+
+               # FTP INFO
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
+               if client.nil? then
+                       puts "Can't access server #{result[0]}:#{result[1]}"
+                       exit(-1)
                end
                end
+               client.send "QUERY|FTP"
+               result0 = client.receive_data()
+               if result0.nil? then
+                       client.terminate
+                       exit(-1)
+               end
+               result0 = result0[0].split(",").map { |x| x.strip }
+               ip = result0[0]
+               username = result0[1]
+               passwd = result0[2]
+               client.terminate
 
 
+               # download
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
+               if client.nil? then
+                       puts "Can't access server #{result[0]}:#{result[1]}"
+                       exit(-1)
+               end
+               file_name = option[:file]
+               client.send("DOWNLOAD|#{file_name}")
+               result = client.receive_file(ip, username, passwd, "./#{file_name}")
+               client.terminate
+               if not result then
+                       puts "Downloading file failed!.. #{option[:file]}"
+                       exit(-1)
+               else
+                       puts "Downloading file succeeded!"
+               end
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
index 66aed201af01f9313e756e77847048422488163d..fd881ffc7532c28bedcc5b31feab14f2d26d0fb9 100755 (executable)
--- a/build-svr
+++ b/build-svr
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby -d 
+#!/usr/bin/ruby -d
 
 =begin
  
 
 =begin
  
@@ -32,6 +32,7 @@ require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/build_server"
 require "utils"
 $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"
 
 require "BuildServerOptionParser"
 require "BuildServerController"
 
@@ -39,49 +40,113 @@ require "BuildServerController"
 begin
        option = option_parse
 rescue => e
 begin
        option = option_parse
 rescue => e
-       puts "Option parse error"
        puts e.message
        exit 0
 end
 
        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 specified, use host os type
+# if "--os" is not specified, set it as default 
 if option[:os].nil? then
 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
+    option[:os] = "default"
 end 
 
 end 
 
-
-
 begin
 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"
+        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 " <ip>:<port>"
+            exit 1
+        end
+        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://<usrename>:<passwd>@<address>:<port>"
+            exit 1
+        end
+        pkgsvr_addr = svr_result[0]
+        pkgsvr_port = svr_result[1]
+        ftpsvr_addr = ftp_result[0]
+        ftpsvr_port = ftp_result[1]
+        ftpsvr_username = ftp_result[2]
+        ftpsvr_passwd = ftp_result[3]
+               BuildServerController.create_server( option[:name], Utils::WORKING_DIR, option[:url], pkgsvr_addr, pkgsvr_port, option[:pid], ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd )
        when "remove"
                BuildServerController.remove_server( option[:name] ) 
        when "start"
        when "remove"
                BuildServerController.remove_server( option[:name] ) 
        when "start"
-               BuildServerController.start_server( option[:name], option[:port] ) 
+               if( option[:child] ) then # Child Process
+                       BuildServerController.start_server( option[:name], option[:port] ) 
+               else  # Parent Process
+                       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.execute_shell_generate("#{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]}" 
+                                               cmd = Utils.execute_shell_generate(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
+               end
        when "stop"
                BuildServerController.stop_server( option[:name] ) 
        when "stop"
                BuildServerController.stop_server( option[:name] ) 
-       when "add"
-               BuildServerController.add_friend_server( option[:name], option[:domain], option[:port] ) 
+       when "upgrade"
+               BuildServerController.upgrade_server( option[:name] ) 
+       when "add-svr"
+               if not option[:domain].nil? then
+               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 " <ip>:<port>"
+               exit 1
+               end
+               pkgsvr_addr = svr_result[0]
+               pkgsvr_port = svr_result[1]
+                       BuildServerController.add_friend_server( option[:name], pkgsvr_addr, pkgsvr_port ) 
+               elsif not option[:url].nil? then
+                       BuildServerController.add_remote_package_server( option[:name], option[:url], option[:proxy] ) 
+               end
+       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] ) 
+               else
+                       BuildServerController.add_binary_project( option[:name], option[:pid], 
+                               option[:package], option[:passwd], option[:os] ) 
+               end
+       when "add-os"
+               BuildServerController.add_target_os( option[:name], option[:os] ) 
+       when "fullbuild"
+               BuildServerController.build_all_projects( option[:name] ) 
+       when "register"
+               BuildServerController.register_package( option[:name], option[:package] ) 
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
diff --git a/doc/DIBS_Advanced_Guide.pdf b/doc/DIBS_Advanced_Guide.pdf
new file mode 100644 (file)
index 0000000..4e90588
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 (file)
index 0000000..74fba2e
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 (file)
index 0000000..5fd43ac
Binary files /dev/null and b/doc/Tizen_SDK_Package_Guide.pdf differ
index 7ff849a23ed9c365cf151838c61a91d9456df549..05ef573ae3de9945bb1f510a051e800e1dfee693 100755 (executable)
@@ -15,20 +15,17 @@ build()
 # install
 install() 
 {
 # 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/
+       DOC_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/documents
        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/
        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/upgrade $BIN_DIR/
        cp -f $SRCDIR/AUTHORS $DOC_DIR/
        cp -f $SRCDIR/LICENSE $DOC_DIR/
        cp -f $SRCDIR/NOTICE $DOC_DIR/
        cp -f $SRCDIR/AUTHORS $DOC_DIR/
        cp -f $SRCDIR/LICENSE $DOC_DIR/
        cp -f $SRCDIR/NOTICE $DOC_DIR/
+       cp -f $SRCDIR/doc/* $DOC_DIR/
+       echo $VERSION > $BIN_DIR/VERSION
 }
 }
-
-
-$1
-echo "$1 success"
-
diff --git a/package/build.macos b/package/build.macos
new file mode 100644 (file)
index 0000000..05ef573
--- /dev/null
@@ -0,0 +1,31 @@
+#!/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/
+       DOC_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/documents
+       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 -f $SRCDIR/upgrade $BIN_DIR/
+       cp -f $SRCDIR/AUTHORS $DOC_DIR/
+       cp -f $SRCDIR/LICENSE $DOC_DIR/
+       cp -f $SRCDIR/NOTICE $DOC_DIR/
+       cp -f $SRCDIR/doc/* $DOC_DIR/
+       echo $VERSION > $BIN_DIR/VERSION
+}
diff --git a/package/build.windows b/package/build.windows
new file mode 100644 (file)
index 0000000..05ef573
--- /dev/null
@@ -0,0 +1,31 @@
+#!/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/
+       DOC_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/documents
+       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 -f $SRCDIR/upgrade $BIN_DIR/
+       cp -f $SRCDIR/AUTHORS $DOC_DIR/
+       cp -f $SRCDIR/LICENSE $DOC_DIR/
+       cp -f $SRCDIR/NOTICE $DOC_DIR/
+       cp -f $SRCDIR/doc/* $DOC_DIR/
+       echo $VERSION > $BIN_DIR/VERSION
+}
index 8f8eda216f19f87ec08dc9ef341bbdc07a03de08..cf38c950db6228c8b802873b15e5de220e0a8bb4 100644 (file)
@@ -1,15 +1,8 @@
-Package : dibs
-Version : 0.20.9
-Maintainer : taejun ha<taejun.ha@samsung.com>, jiil hyoun <jiil.hyoun@samsung.com>, <donghyouk.yang@samsung.com>, donghee yang< donghee.yang@samsung.com >
-Description : Distribute Inteligent Build System
-OS : linux
-Build-host-os : linux
 Source : dibs
 Source : dibs
+Version :1.0.6
+Maintainer : taejun ha<taejun.ha@samsung.com>, jiil hyoun <jiil.hyoun@samsung.com>, donghyuk yang <donghyouk.yang@samsung.com>, donghee yang <donghee.yang@samsung.com>, sungmin kim <dev.sungmin.kim@samsung.com
 
 Package : dibs
 
 Package : dibs
-Version : 0.20.9
-Maintainer : taejun ha<taejun.ha@samsung.com>, jiil hyoun <jiil.hyoun@samsung.com>, <donghyouk.yang@samsung.com>, 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
 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 (file)
index 0000000..ce655de
--- /dev/null
@@ -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
index 22b58f3f9868e8ce282f98ae327e8b7fdcaa80ec..39e788282a609b9a933689a4691fb8b8426a19df 100755 (executable)
--- a/pkg-build
+++ b/pkg-build
@@ -36,18 +36,24 @@ require "packageServer"
 require "Builder"
 require "optionparser"
 
 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
 
 
 #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
 # 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
 end
 
 path = Dir.pwd
@@ -62,25 +68,27 @@ if not option[:url].nil? then
        builder = Builder.get("default") 
                if builder.pkgserver_url != option[:url] then
                        puts "Package server URL has been changed! Creating new builder..."
        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..."
                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")  
        rescue
                puts "Default builder does not exist! Creating new builder..."
        end
 else # if url is not specified
        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 
 
 #build project
        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!"
        puts "Build Failed!"
+    exit 1    
 else
        puts "Build Succeeded!"
 else
        puts "Build Succeeded!"
+    exit 0    
 end
 
 end
 
index de48dce4047eda5929f71b6c07f935b65f872c2e..9315d88e7f272d719de772b525e942f60525ee82 100755 (executable)
--- a/pkg-clean
+++ b/pkg-clean
@@ -46,6 +46,12 @@ option = parse
 
 #generate server when local package server is not set
 
 
 #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
+
 begin 
        builder = Builder.get("default")  
 rescue
 begin 
        builder = Builder.get("default")  
 rescue
diff --git a/pkg-cli b/pkg-cli
index 3a0458187d901861494608dfe3affd7da1bad40c..df9a164be1b629db3e45074d2b53e798538f7e53 100755 (executable)
--- a/pkg-cli
+++ b/pkg-cli
@@ -42,93 +42,73 @@ require "packageServer"
 #set global variable
 @WORKING_DIR = nil
 
 #set global variable
 @WORKING_DIR = nil
 
-$log = Logger.new('.log', 'monthly')
-
 #option parsing 
 begin
        option = option_parse
 rescue => e
        # if option parse error print help message
 #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
 
        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
 #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] 
 when "update" then
     client = Client.new( option[:url], nil, nil )
 end
 
 case option[:cmd] 
 when "update" then
     client = Client.new( option[:url], nil, nil )
-    client.update()
+    #client.update()
 when "clean" then
     client = Client.new( nil, option[:loc], nil )
     client.clean(option[:f])
 when "download" then
     client = Client.new( option[:url], option[:loc], nil )
 when "clean" then
     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
+    #if not option[:url].nil? then
+    #    client.update()
+    #end
        file_loc = client.download( option[:pkg], option[:os], option[:t] )
        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 )
 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] ) 
+    #if not option[:url].nil? then
+    #    client.update()
+    #end
+    client.install( option[:pkg], option[:os], option[:t], option[:f] ) 
 when "install-file" then
 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] )
 when "upgrade" then
     client = Client.new( option[:url], option[:loc], nil )
 when "uninstall" then
     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
+    #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 )
     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
+    #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 )
     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
+    #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 )
        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
+    #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|
        result = client.show_pkg_list( option[:os] )
     if not result.nil? and not result.empty? then
         result.each do |i|
@@ -175,6 +155,6 @@ when "install-dep" then
     ret[-3..-1] = ""
     puts ret
 else
     ret[-3..-1] = ""
     puts ret
 else
-       raise RuntimeError, "input option incorrect : #{option[:cmd]}"
+    raise RuntimeError, "Input is incorrect : #{option[:cmd]}"
 end
 
 end
 
diff --git a/pkg-svr b/pkg-svr
index 7a80d61d7064dcbf7877fe022a821f06edac2344..3e3d597183ec93de3fd0de2ac25abab9683e64db 100755 (executable)
--- a/pkg-svr
+++ b/pkg-svr
@@ -39,10 +39,7 @@ require "serverOptParser"
 begin
        option = option_parse
 rescue => e
 begin
        option = option_parse
 rescue => e
-       puts "\n=============== Error occured =============================="
        puts e.message
        puts e.message
-       puts e.backtrace.inspect
-       puts "=============================================================\n"
        exit 0
 end
 
        exit 0
 end
 
@@ -66,15 +63,15 @@ begin
        when "create"  
                server.create( option[:id], option[:dist], option[:url], option[:loc] )
        when "register"
        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"
        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] )
        when "add-dist"
                server.add_distribution( option[:dist], option[:url], option[:clone] )
        when "sync"
                server.sync( option[:dist], option[:force] )
        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"
                if not option[:force] then
                        puts  "Do you want to really? then input \"YES\""
        when "remove"
                if not option[:force] then
                        puts  "Do you want to really? then input \"YES\""
@@ -87,17 +84,35 @@ begin
                        end
                end
 
                        end
                end
 
-               server.remove_server( option[:id] )
+               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_dist( option[:dist] )
        when "remove-pkg"
        when "remove-pkg"
-               server.remove_pkg( option[:id], option[:dist], option[:bpkgs], option[:os] )
+               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 
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
 rescue => e 
-       puts "\n=============== Error occured =============================="
        puts e.message
        puts e.message
-       puts e.backtrace.inspect
-       puts "=============================================================\n"
 end
 
 
 end
 
 
diff --git a/src/build_server/BinaryUploadProject.rb b/src/build_server/BinaryUploadProject.rb
new file mode 100644 (file)
index 0000000..28f81ea
--- /dev/null
@@ -0,0 +1,91 @@
+=begin
+ BinaryUploadProject.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "CommonProject.rb"
+require "RegisterPackageJob.rb"
+require "Version.rb"
+require "PackageManifest.rb"
+
+
+class BinaryUploadProject < CommonProject
+       attr_accessor :pkg_name
+
+       # initialize
+       def initialize( name, pkg_name, server, os_list )
+               super(name, "BINARY", server, os_list)
+               @pkg_name = pkg_name
+       end
+
+
+       # create new job
+       def create_new_job( filename, dock = "0" )
+        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 return nil end
+
+               # check os name
+               if not @server.supported_os_list.include? os then return nil end
+
+               # check package info
+               file_path = "#{@server.transport_path}/#{dock}/#{filename}"
+               if not File.exist? file_path then return nil end
+
+               pkginfo_dir = "#{@server.path}/projects/#{@name}/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
+                       return nil
+               end
+               begin
+                       pkginfo =PackageManifest.new("#{pkginfo_dir}/pkginfo.manifest")
+               rescue => e
+                       puts e.message
+                       return nil
+               end
+               pkgs =  pkginfo.get_target_packages(os)
+               if pkgs.count != 1 then return nil end
+               if pkgs[0].package_name != @pkg_name then return nil end
+
+               new_job = RegisterPackageJob.new( file_path, self, @server )
+
+               return new_job
+       end
+
+
+       def include_package?(name, version=nil, os=nil)
+               if name == @pkg_name then 
+                       return true 
+               else
+                       return false
+               end
+       end
+end
index 1adf0b07096f5028118332650e3205c263e6ca9d..8cc9e60ad3d0207b77858d584ff3e80f1b445e00 100644 (file)
@@ -26,51 +26,151 @@ Contributors:
 - S-Core Co., Ltd
 =end
 
 - S-Core Co., Ltd
 =end
 
+$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 require 'optparse'
 require 'optparse'
+require 'utils'
 
 
-def option_parse 
+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: build-cli build -N <project name> -d <server address> [-o <os>] [-w <password>] [--async]"    
+        end
+
+    when "resolve" then
+        if options[:project].nil? or options[:project].empty? or
+                options[:domain].nil?  or options[:domain].empty? then
+            raise ArgumentError, "Usage: build-cli resolve -N <project name> -d <server address> [-o <os>] [-w <password>] [--async]"    
+        end
+
+    when "query" then
+        if options[:domain].nil? or options[:domain].empty? then
+            raise ArgumentError, "Usage: build-cli query -d <server address>"    
+        end                
+
+    when "query-system" then
+        if options[:domain].nil? or options[:domain].empty? then
+            raise ArgumentError, "Usage: build-cli query-system -d <server address>"    
+        end                
+
+    when "query-project" then
+        if options[:domain].nil? or options[:domain].empty? then
+            raise ArgumentError, "Usage: build-cli query-project -d <server address>"    
+        end               
+    when "query-job" then
+        if options[:domain].nil? or options[:domain].empty? then
+            raise ArgumentError, "Usage: build-cli query-job -d <server address>"    
+        end                
+
+    when "cancel" then
+        if options[:job].nil? or options[:job].empty? or
+                options[:domain].nil? or options[:domain].empty? then
+            raise ArgumentError, "Usage: build-cli cancel -j <job number> -d <server address> [-w <password>]"    
+        end
+    when "register" then
+        if options[:package].nil? or options[:package].empty? or
+            options[:domain].nil? or options[:domain].empty? or
+            options[:fdomain].nil? or options[:fdomain].empty? then
+            raise ArgumentError, "Usage: build-cli register -P <package file> -d <server address>  -t <ftp server url> [-w <password>]"    
+        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 = {}
     options = {}
-    banner = "Usage: build-cli {build|resolve|query} ..." + "\n" \
-               + "\t" + "build-cli build -g <git-repository> -c <git-commit> [-d <svr domain>] [-p <svr-port>] [-o <os>] [-a <async>] " + "\n" \
-               + "\t" + "build-cli resolve -g <git-repository> -c <git-commit> [-d <svr domain>] [-p <svr-port>] [-o <os>] [-a <async>] " + "\n" \
-               + "\t" + "build-cli query [-d <svr domain>] [-p <svr-port>]" + "\n" 
+    banner = "Requiest service to build-server command-line tool." + "\n" \
+       + "\n" + "Usage: build-cli <SUBCOMMAND> [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" + "build-cli build -N <project name> -d <server address> [-o <os>] [-w <password>] [--async]" + "\n" \
+       + "\t" + "build-cli resolve -N <project name> -d <server address> [-o <os>] [-w <password>] [--async]" + "\n" \
+       + "\t" + "build-cli query -d <server address>" + "\n" \
+       + "\t" + "build-cli query-system -d <server address>" + "\n" \
+       + "\t" + "build-cli query-project -d <server address>" + "\n" \
+       + "\t" + "build-cli query-job -d <server address>" + "\n" \
+       + "\t" + "build-cli cancel -j <job number> -d <server address> [-w <password>] " + "\n" \
+       + "\t" + "build-cli register -P <file name> -d <server address> -t <ftp server url> [-w <password>] " + "\n" \
+       + "\n" + "Options:" + "\n"
+
+    optparse = OptionParser.new(nil, 32, ' '*8) do|opts|
 
 
-    optparse = OptionParser.new do|opts|
         # Set a banner, displayed at the top
         # of the help screen.
 
                opts.banner = banner 
 
         # Set a banner, displayed at the top
         # of the help screen.
 
                opts.banner = banner 
 
-               opts.on( '-g', '--git <git-repository>', 'git repository' ) do|git|
-            options[:git] = git
-        end
-
-               opts.on( '-c', '--commit <git-commit>', 'git commit id/tag' ) do|git|
-            options[:commit] = git
+               opts.on( '-N', '--project <project name>', '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
         end
 
         options[:domain] = nil
-               opts.on( '-d', '--domain <build-svr-domain>', 'remote build server ip address. default 127.0.0.1' ) do|domain|
+               opts.on( '-d', '--address <server address>', 'build server address: 127.0.0.1:2224' ) do|domain|
             options[:domain] = domain
         end
                
             options[:domain] = domain
         end
                
-        options[:port] = nil
-               opts.on( '-p', '--port <build-svr-port>', 'remote build server port. default 2222' ) do|port|
-            options[:port] = port
-        end
-               
         options[:os] = nil
         options[:os] = nil
-               opts.on( '-o', '--os <operating system>', 'target operating system linux/windows/darwin' ) do|os|
+           opts.on( '-o', '--os <operating system>', '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"
             options[:os] = os
         end
 
         options[:async] = "NO"
-               opts.on( '-a', '--async', 'asynchronous job' ) do
+               opts.on( '--async', 'asynchronous job' ) do
             options[:async] = "YES"
             options[:async] = "YES"
+               end
+
+        options[:noreverse] = "NO"
+               opts.on( '--noreverse', 'do not check reverse build' ) do
+            options[:noreverse] = "YES"
         end
        
         end
        
-               opts.on( '-h', '--help', 'display this information' ) do
-            puts opts
+               opts.on( '-j', '--job <job number>', 'job number' ) do|job|
+            options[:job] = job
+        end
+
+        options[:passwd] = ""
+               opts.on( '-w', '--passwd <password>', 'password for managing project' ) do|passwd|
+            options[:passwd] = passwd
+        end
+
+               opts.on( '-P', '--pkg <package file>', 'package file path' ) do|package|
+            options[:package] = package.strip
+        end
+
+               opts.on( '-t', '--ftp <ftp server url>', 'ftp server url: ftp://dibsftp:dibsftp@127.0.0.1' ) do|domain|
+            options[:fdomain] = domain
+        end
+
+               opts.on( '-h', '--help', 'display help' ) do
+            opts.help.split("\n").each {|op| puts op if not op.include? "--noreverse"}
+                       exit
+        end
+
+               opts.on( '-v', '--version', 'display version' ) do
+            puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
                        exit
         end
                
                        exit
         end
                
@@ -78,19 +178,26 @@ def option_parse
     
        cmd = ARGV[0] 
 
     
        cmd = ARGV[0] 
 
-    if cmd.eql? "build" or cmd.eql? "resolve" or cmd.eql? "query" or 
-                cmd =~ /(help)|(-h)|(--help)/ then
+    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 
+        if cmd.eql? "help" then
                        ARGV[0] = "-h" 
                end
 
         options[:cmd] = ARGV[0]
     else
                        ARGV[0] = "-h" 
                end
 
         options[:cmd] = ARGV[0]
     else
-        raise ArgumentError, banner
+        raise ArgumentError, "Usage: build-cli <SUBCOMMAND> [OPTS] or build-cli -h"
     end
 
     optparse.parse!
     end
 
     optparse.parse!
+
+    option_error_check options
    
     return options
 end 
    
     return options
 end 
index 94f8bb1bcd55fb88965bc482964f968d3b1942ce..647d755e344df6a53fad545da24c75e7d3b341f9 100644 (file)
@@ -30,16 +30,45 @@ Contributors:
 
 $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 require "log"
 
 $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 require "log"
+require 'timeout'
+require "fileTransfer"
+require "net/ftp"
+require 'thread'
+
+ATTEMPTS = ["first", "second", "third"]
 
 class BuildCommServer
 
 class BuildCommServer
-       VERSION = "1.2.0"
+       VERSION = "1.5.0"
+
+       private_class_method :new
 
 
-       def initialize(port, log)
+       def initialize(port, log, ftp_url, cache_dir)
                @port = port
                @port = port
-               @tcp_server = TCPServer.open( port )
                @log = log
                @log = log
+               @ftp_url = ftp_url
+               @cache_dir = cache_dir
+               @tcp_server = TCPServer.open( port )
+               @download_cache_mutex = Mutex.new
        end
 
        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 = Log.new(nil)                              
+               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)
 
        # wait for connection and handle request
        def wait_for_connection(quit_loop)
@@ -47,8 +76,9 @@ class BuildCommServer
                        req = @tcp_server.accept                
        
                        begin
                        req = @tcp_server.accept                
        
                        begin
-                               yield req
+                               yield req if block_given?
                        rescue
                        rescue
+                               @log.error $!
                                @log.error "Caught a connection exception"
                                req.close
                        end
                                @log.error "Caught a connection exception"
                                req.close
                        end
@@ -89,30 +119,275 @@ class BuildCommServer
        end
 
 
        end
 
 
+       def send_file(req, src_file)
+               # 1. send "READY"
+               # 2. If "FTP,ip,username,passwd" is received,
+               #     Upload the src file using server's ftp_url.
+               #     if then ftp_url is nil, use the url on "FTP" message instead
+               #     After uploading, send "UPLOADED,ftp_filepath"
+               # 3. If "SUCC" is received, remove the file on FTP server
+
+        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 upload file"                        
+            while l = req.gets()
+                tok = l.split(",").map { |x| x.strip }
+                cmd = tok[0].strip
+                if cmd == "FTP" then
+                    if tok.count < 5 then
+                        @log.error "Server received wrong REQ : #{l.strip}"
+                        req.puts "ERROR"
+                        return false
+                    end
+
+                                       # get ftp connection info
+                                       if @ftp_url.nil? then
+                       ip = tok[1].strip
+                       port = tok[2].strip
+                       username = tok[3].strip
+                       passwd = tok[4].strip
+                       @log.info "Server received ftp server infomation from client : [#{ip}, #{port}]"
+                                       else
+                       url_contents = Utils.parse_ftpserver_url(@ftp_url)
+                                               ip = url_contents[0]
+                                               port = url_contents[1]
+                       username = url_contents[2]
+                       passwd = url_contents[3]
+                                       end
+
+                                       # upload to ftp server
+                                       ftp_filepath = nil                                      
+                                       for attempt in ATTEMPTS
+                           ftp_filepath = FileTransfer.putfile(ip, port, username, passwd, src_file, @log)
+                                               if !ftp_filepath.nil? then break;
+                                               else @log.info "Server is the #{attempt} upload attempt fails" end
+                                       end                                             
+                                       if ftp_filepath.nil? then
+                                               req.puts "ERROR"                                                        
+                                               return false 
+                                       else 
+                                               @log.info "Server is the #{attempt} successful attempt to upload file: [#{File.basename(src_file)}]" 
+                                       end
+                    req.puts "UPLOADED,#{ftp_filepath}"
+                elsif cmd == "SUCC" then
+                    @log.info "Client downloaded file successfully"
+                    FileTransfer.cleandir(ip, port, username, passwd, ftp_filepath, @log)
+                    @log.info "Cleaned temporary dir on FTP server: #{ftp_filepath}"
+                    break 
+                               elsif cmd == "ERROR" then                                       
+                    @log.error "Client failed to download file"
+                                       return false                                    
+                               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)
+               # 1. send "READY"
+               # 2. If "UPLOADED,ip,port,file_path,username,passwd" is received,
+               #    Download the file using my ftp_url.
+               #    If ftp_url is nil, use the url on "UPLOADED" messge instead
+               #    After downloading it, send "SUCC"
+
+               begin
+            req.puts "READY"
+                       while l = req.gets()
+                               tok = l.split(",").map { |x| x.strip }
+                               cmd = tok[0].strip
+                               if cmd == "CHECK_CACHE" then
+                                       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"
+                                               break   
+                                       else
+                                               @log.info "Cached file not found!#{file_name}"
+                                               req.puts "NOT_CACHED"
+                                       end
+                               elsif cmd == "UPLOADED" then
+                                       @log.info "Client uploaded file to ftp server successful"
+                                       if tok.count < 6 then
+                                               @log.error "Server received wrong REQ : #{l.strip}"
+                                               req.puts "ERROR"
+                                               return false
+                                       end
+                                       filepath = tok[3].strip
+
+                                       # get ftp connection info
+                                       if @ftp_url.nil? then
+                                               ip = tok[1].strip
+                                               port = tok[2].strip
+                                               username = tok[4].strip
+                                               passwd = tok[5].strip
+                                               @log.info "Client sent ftp server infomations [#{ip}, #{port}]"
+                                       else
+                                               url_contents = Utils.parse_ftpserver_url(@ftp_url)
+                                               ip = url_contents[0]
+                                               port = url_contents[1]
+                                               username = url_contents[2]
+                                               passwd = url_contents[3]
+                                       end
+
+                                       # download from ftp server
+                                       dst_filepath = nil
+                                       for attempt in ATTEMPTS
+                           dst_filepath = FileTransfer.getfile(ip, port, username, passwd, filepath, dst_file, @log)
+                                               if not dst_filepath.nil? then break
+                                               else 
+                                                       @log.warn "Server is the #{attempt} download attempt fails" 
+                                               end                                                     
+                                       end                                     
+                                       if dst_filepath.nil? then 
+                                                       req.puts "ERROR"                                                        
+                                                       return false                                                                                            
+                                       else @log.info " Server is the #{attempt} successful attempt to download" end
+                                       
+                                       # add to cache
+                                       if not @cache_dir.nil? then
+                                       if File.exist? dst_file and File.directory? dst_file then 
+                                                       target_file = File.join(dst_file,File.basename(dst_filepath))
+                                       else 
+                                                       target_file = dst_file 
+                                               end
+                                               add_download_cache(target_file)
+                                       end
+
+                    req.puts "SUCC"
+                    break
+                               elsif cmd == "ERROR" then
+                                       @log.error "Client failed to upload the file"
+                                       return false                            
+                               else
+                                       @log.warn "Unhandled message: #{l}"
+                               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.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 {
+                       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 { |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
+                       }
+
+                       return found
+               }
+       end
+
+
+       private
+       def add_download_cache(dst_file)
+               file_name = File.basename(dst_file)
+               cache_file = "#{@cache_dir}/#{file_name}"
+               @download_cache_mutex.synchronize {
+                       # copy & touch
+                       FileUtils.copy_file(dst_file, cache_file)
+                       FileUtils.touch cache_file
+               }
+       end
 end
 
 
 class BuildCommClient
 end
 
 
 class BuildCommClient
-       VERSION = "1.2.0"
+       VERSION = "1.5.0"
 
        private_class_method :new
 
 
        private_class_method :new
 
-       def initialize(socket)
+       def initialize(socket, log)
+        @log = log
                @socket = socket
        end
 
 
        # create
                @socket = socket
        end
 
 
        # create
-       def self.create(ip, port)
+       # if sec 0 or nil then not set timeout. it's timeout spec
+       def self.create(ip, port, log = nil, sec = 5)
                # open socket
                # open socket
+               socket = nil
                begin
                begin
-                       socket = TCPSocket.open( ip, port )
+                       timeout(sec) do
+                               socket = TCPSocket.open( ip, port )
+                       end
+               rescue Timeout::Error
+                       return nil
                rescue
                        # unknown exception
                        return nil
                rescue
                        # unknown exception
                        return nil
@@ -120,10 +395,14 @@ class BuildCommClient
 
                # refused
                if socket.nil? then
 
                # refused
                if socket.nil? then
-                       return nil 
-               end 
+                       return nil
+               end
+               
+               if log.nil? then
+                       log = Log.new(nil)                              
+               end                             
 
 
-               return new(socket)
+               return new(socket, log)
        end
 
 
        end
 
 
@@ -140,7 +419,7 @@ class BuildCommClient
                begin
                        l = @socket.gets()
 
                begin
                        l = @socket.gets()
 
-                       if @socket.nil? then 
+                       if l.nil? then 
                                puts "Connection refused"
                                return false 
                        end
                                puts "Connection refused"
                                return false 
                        end
@@ -173,9 +452,12 @@ class BuildCommClient
 
                begin
                        # get first line
 
                begin
                        # get first line
-                       l = @socket.gets()
+                       l = nil
+                       timeout(5) do 
+                               l = @socket.gets()
+                       end
 
 
-                       if @socket.nil? then 
+                       if l.nil? then 
                                return false 
                        end
 
                                return false 
                        end
 
@@ -190,9 +472,13 @@ class BuildCommClient
                                if line.strip == "=CHK" then next end
 
                                # print
                                if line.strip == "=CHK" then next end
 
                                # print
-                               yield line.strip
+                               yield line.strip if block_given?
                        end
                        end
-               rescue
+               rescue Timeout::Error
+            puts "WARN: Connection timed out"
+                       return false
+               rescue => e
+            puts e.message
                        return false
                end
 
                        return false
                end
 
@@ -207,7 +493,7 @@ class BuildCommClient
                begin
                        l = @socket.gets()
 
                begin
                        l = @socket.gets()
 
-                       if @socket.nil? then 
+                       if l.nil? then 
                                puts "Connection refused"
                                return nil
                        end
                                puts "Connection refused"
                                return nil
                        end
@@ -235,6 +521,133 @@ class BuildCommClient
        end
 
 
        end
 
 
+       def send_file(ip, port, username, passwd, src_file)
+        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}"
+                               return false
+                       end
+
+                       # 1. If "READY" is received, upload src file to FTP server
+                       #    After uploading it, send "UPLOADED,ip,file_path,username,passwd"
+                       # 2. If "SUCC" is received, remove the file on FTP server
+            while line = @socket.gets()
+                if line.strip == "READY" then
+                       @log.info "Server is ready to receive file"
+                                       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}"
+                elsif line.strip == "CACHED" then
+                    @log.info "Server already has cached file"
+                elsif line.strip == "NOT_CACHED" then
+                       @log.info "Server doest not have cached file"
+                                       ftp_filepath = nil
+                                       for attempt in ATTEMPTS
+                       ftp_filepath = FileTransfer.putfile(ip, port, username, passwd, src_file, @log)
+                                               if !ftp_filepath.nil? then break;
+                                               else @log.info "Client is the #{attempt} upload attempt fails" end
+                                       end                                             
+                                       if ftp_filepath.nil? then 
+                                               send "ERROR"                                                    
+                                               return false 
+                                       else @log.info "Client is the #{attempt} successful attempt to upload file" end
+                    send "UPLOADED,#{ip},#{port},#{ftp_filepath},#{username},#{passwd}"
+                elsif line.strip == "SUCC" then 
+                    @log.info "Server downloaded file sucessfully"
+                    FileTransfer.cleandir(ip, port, username, passwd, ftp_filepath, @log)
+                    @log.info "Client cleaned temporary dir on ftp server: #{ftp_filepath}"
+                elsif line.strip == "ERROR" then
+                    @log.error "Server failed to download the file. Please check server log"
+                    return false
+                elsif line.strip == "=END" then
+                    break
+                end
+            end
+        rescue => e
+            puts "[BuildCommClient] Exception" 
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return false                    
+               end
+
+               return true
+       end
+
+
+       # return file
+       def receive_file(ip, port, username, passwd, dst_file)
+               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}"
+                               return false
+                       end
+
+                       # 1. If "READY" is received, send "FTP,ip,port,username,passwd"
+                       # 2. if "UPLOADED,ftp_file_path" is received,
+                       #    Download the file
+                       #    Send "SUCC"
+                       # 3. If "SUCC" is received, remove the file on FTP server
+            while line = @socket.gets()
+                cmd = line.split(",")[0].strip
+                #@log.info "[BuildCommClient] Received \"#{cmd}\" message from BuildCommServer"
+                if cmd == "READY" then
+                    send "FTP,#{ip},#{port},#{username},#{passwd}"
+                    @log.info "Client sent ftp server infomation to server : [#{ip}, #{port}]"
+                elsif cmd == "UPLOADED" then
+                    tok = line.split(",")
+                    if tok.length < 2 then
+                        @log.error "Client received wrong REQ : #{line.strip}"
+                        return false
+                    end
+                    ftp_filepath = tok[1].strip
+                                       @log.info "Server uploaded file sucessfully"                                    
+                                       dst_filepath = nil
+                                       for attempt in ATTEMPTS
+                           dst_filepath = FileTransfer.getfile(ip, port, username, passwd, ftp_filepath, dst_file, @log)
+                                               if not dst_filepath.nil? then break
+                                               else 
+                                                       @log.warn "Client is the #{attempt} download attempt fails" 
+                                               end                                                     
+                                       end                                     
+                                       if dst_filepath.nil? then 
+                                               send "ERROR"                                                    
+                                               return false
+                                       else @log.info "Client is the #{attempt} successful attempt to download" end
+                    send "SUCC"
+                elsif cmd == "ERROR" then
+                    @log.error "Server failed to upload file. Check server log"
+                    return false
+                elsif cmd == "=END" then
+                    break
+                end
+            end
+               rescue => e
+            puts "[BuildCommServer] Exception" 
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return false                    
+               end
+
+               return true
+       end
+
+
        def terminate
                @socket.close
        end
        def terminate
                @socket.close
        end
index f29bdaf40e60e82349d503a0ec5918f62df74623..223d752950606b4958f3194688c1b6a1749405f4 100644 (file)
@@ -1,5 +1,5 @@
 =begin
 =begin
+
  BuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
  BuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -35,64 +35,318 @@ require "client.rb"
 require "PackageManifest.rb"
 require "Version.rb"
 require "Builder.rb"
 require "PackageManifest.rb"
 require "Version.rb"
 require "Builder.rb"
+require "RemoteBuilder.rb"
 require "BuildServer.rb"
 require "JobLog.rb"
 require "mail.rb"
 require "BuildServer.rb"
 require "JobLog.rb"
 require "mail.rb"
+require "utils.rb"
+require "ReverseBuildChecker.rb"
 
 class BuildJob
 
 
 class BuildJob
 
-       attr_accessor :blocked_by
+       attr_accessor :id, :server, :pre_jobs, :os, :type
+       attr_accessor :status, :pkginfo, :log, :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
 
        # initialize
 
        # initialize
-       def initialize ()
-               @blocked_by = []
+       def initialize (id, project, os, server)
+               @id = id
+               @project = project
+               @os = os
+               @server = server
+               @type = "BUILD"
+
+               @status = "JUST_CREATED"
+               @cancel_state = "NONE"
+        @resolve = false
+               @host_os = Utils::HOST_OS
+               @pkgserver_url = @server.pkgserver_url
+               @job_root = "#{@server.path}/jobs/#{@id}"
+               @source_path = @job_root+"/temp"
+               @job_working_dir=@job_root+"/works"
+               @buildroot_dir = "#{@job_root}/buildroot"
+               @pre_jobs = [] #pre-requisite jobs
+
+               # 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
+
+
+       def get_project()
+               return @project
+       end
+
+
+       # set parent
+       def set_parent_job( parent )
+               # if parent exists, share build-root
+               @parent = parent
+       end
+
+       # get parent
+       def get_parent_job()
+               return @parent
+       end
+
+
+       def is_sub_job?
+               return (not @parent.nil?)
+       end
+
+
+       def get_sub_jobs
+               return []
+       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 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
+
+
+       # set logger 
+       def set_logger( logger )
+               @log =  logger
+       end
+
+
+       # add external packages to overwrite before build
+       def add_external_package( file_name )
+               @external_pkgs.push "#{@job_root}/external_pkgs/#{file_name}"
        end
 
        end
 
+       
        # execute
        # execute
-       def execute
+       def execute(sync=false)
                @log.info( "Invoking a thread for building Job #{@id}", Log::LV_USER)
                if @status == "ERROR" then return  end
                @thread = Thread.new {
                @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()
-               } 
+                       begin
+                               thread_main()
+                               if not is_sub_job? then terminate() end
+                       rescue => e
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                       end
+               }
+
+               if sync then
+                       @thread.join
+               end
+               
+               return true      
        end
 
 
        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()
-               } 
+       #terminate
+       def terminate()
+               #do noting
+       end
+
+
+       #cancel
+       def cancel()
+               # 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}"
+                               result1 = client.receive_data()
+                               if result1.nil? then
+                                       @log.info( "cancel operation failed [connection error] !!", Log::LV_USER)
+                               else
+                                       @log.info(result1, Log::LV_USER)
+                               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)
        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 true
                        end
                end
-               
                return false
        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)
+               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
        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
+                         does_depend_on?(other_job) or
+                         does_depended_by?(other_job) then
 
                        return true
                else
 
                        return true
                else
@@ -102,35 +356,53 @@ class BuildJob
 
 
        def has_same_packages?( wjob )
 
 
        def has_same_packages?( wjob )
-               for pkg in @pkginfo.packages
-                       for wpkg in wjob.pkginfo.packages
+
+               # 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
                                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 )
                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
+               # 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
                                        #puts "Removed from candiated... A -> B"
                                        return true
                                end
                        end
                end
+               
                return false
        end
 
 
        def does_depended_by?( wjob )
                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
+
+               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
                                        #puts "Checking... A <- B"
                                        return true
                                end
@@ -141,31 +413,135 @@ class BuildJob
 
 
        def is_connected?
 
 
        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
                        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
 
                end
 
-               return true
+               return false
        end
 
 
        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{|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)
+                       }
+                       prjs = @server.prjmgr.get_projects_from_pkgs(pkgs)
+                       @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
+               if not @log.nil? then
+                       if @project.nil? or @project.get_latest_log_cnt.nil? then
+                               return "--% (#{log.cnt.to_s} lines) "
+                       else
+                               return ( ( @log.cnt * 100 ) / @project.get_latest_log_cnt ).to_s + "%"
+                       end
+               end
+               # if log is nil then can't figure progress out
+               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
                else
-                       return false
+                       return url,""
                end
        end
                end
        end
+
+
        #
        # PROTECTED METHODS
        #
        #
        # PROTECTED METHODS
        #
@@ -176,52 +552,70 @@ class BuildJob
        def thread_main
                @log.info( "New Job #{@id} is started", Log::LV_USER)
                
        def thread_main
                @log.info( "New Job #{@id} is started", Log::LV_USER)
                
-               # 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
                # 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"
                        @status = "ERROR"
-                       return
+                       return false
                end
 
                # clean build
                end
 
                # clean build
-               if not build()
+               if not build() then
+                       if @is_internal_job then copy_result_files_to_master() end
+
                        @status = "ERROR"
                        @status = "ERROR"
-                       return
+                       return false
                end
 
                # upload
                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"
                        @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"
                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
        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)
 
                @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)
+
+                       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
 
 
-               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
+                       # 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
                                @log.error( "Version must be increased : #{ver_local} <= #{ver_svr}", Log::LV_USER)
                                return false
                        end
@@ -232,127 +626,422 @@ class BuildJob
 
 
        # build dependency version
 
 
        # 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)
        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
 
 
-               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]
-                       else
-                               dep_target_os = @os
+                       if not remote_package_of_dependency_exist?(dep) then
+                               unmet_bdeps.push dep
                        end
                        end
-                       ver_svr = @pkgsvr_client.get_attr_from_pkg( dep.package_name, dep_target_os, "version")
+               end
 
 
-                       if ver_svr.nil?
-                               @log.error( "The package \"#{dep.package_name}\" for build-dependency is not found}", Log::LV_USER)
-                               return false
+               @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.sub_jobs.each { |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 dep.match? ver_svr
-                               @log.error( "Version for build-dependency in not matched : server version => #{ver_svr}", Log::LV_USER)
-                               return false
+                       if not remote_package_of_dependency_exist?(dep) then
+                               unmet_ideps.push dep
                        end
                        end
-               end     
-               
-               return true
+               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 { |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)
+                       }
+                       unmet_ideps.each { |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)
+                       }
+
+                       return false
+               else
+                       return true
+               end
        end
 
 
        # build clean
        def     build()
        end
 
 
        # build clean
        def     build()
-        if @resolve then 
-                       @log.info( "Resolving job...", Log::LV_USER)
+
+               # check there are pending pacakges 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{
+                               @pending_ancestor = get_pending_ancestor_job()
+                       }
+               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
                else
-                       @log.info( "Building job...", Log::LV_USER)
-               end 
+                       # build
+                       build_normal()
+               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)
-                       return false
+
+       # return pending job that wait for me
+       def get_pending_ancestor_job()
+        @server.jobmgr.get_pending_jobs.each do |job|
+            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
                end
-               @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+
+               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}" )
+                       @log.info( " - FTP Server : #{@server.ftp_addr}" )
+               else
+                       builder = Builder.create( "JB#{@id}", @pkgserver_url, @log.path,
+                                "#{@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 : #{@pkgserver_url}" )
+                       @log.info( " - Build Cache Path : #{@server.build_cache_dir}" )
+               end
+               @log.info( " - Log Path : #{@log.path}" )
                
                # set log output
                builder.log.close
                builder.log = @log
 
                
                # 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.jobmgr.get_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?)
+               # 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(@project.repository, @source_path, @os, 
+                                       @is_rev_build_check_job, @git_commit, @no_reverse, local_pkgs)
+                       else
+                               result =  builder.build(@source_path, @os, use_clean, local_pkgs, false )
+                       end
+                       if not result then
+                               @log.error( "Building job failed", Log::LV_USER)
+                               write_log_url()
+                               return false
+                       end
+               end
+
+               # 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
+
+
+       # 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}" )
+                       @log.info( " - FTP Server : #{@server.ftp_addr}" )
+               else
+                       builder = Builder.create( "JB#{@id}", @pkgserver_url, @log.path,
+                                "#{@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 : #{@pkgserver_url}" )
+                       @log.info( " - Build Cache Path : #{@server.build_cache_dir}" )
+               end
+               @log.info( " - Log Path : #{@log.path}" )
+
+               # set log output
+               builder.log.close
+               builder.log = @log
 
                # build 
 
                # build 
-        if @resolve then  
-            @rev_fail_list = builder.build_resolve(@source_path, @os, [], []) 
+               if @is_remote_job then
+                       result = builder.build(@project.repository, @source_path, @os, 
+                               false, @git_commit, @no_reverse, [])
+               else
+               result =  builder.build(@source_path, @os, true, [], false )
+               end
+        if not result then
+            @log.error( "Building job failed", Log::LV_USER)
+                       write_log_url()
+            return false
+        end
 
 
-            # clean build failed
-            if @rev_fail_list.nil? then 
-                @log.error( "Resolve building job failed", Log::LV_USER)
-                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"
+        # 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 
 
 
-            # rev build successed
-            if @rev_fail_list.empty? then 
-                @rev_success_list.each do |s|
-                    s.status = ""
-                end 
-                @status = ""
-            end
+               return true
+       end
 
 
-            @log.info "Enters the PENGING state ..."
-            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
+
+       # 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}" )
+                       @log.info( " - FTP Server : #{@server.ftp_addr}" )
+               else
+                       builder = Builder.create( "JB#{@id}", @pkgserver_url, @log.path,
+                                "#{@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 : #{@pkgserver_url}" )
+                       @log.info( " - Build Cache Path : #{@server.build_cache_dir}" )
+               end
+               @log.info( " - Log Path : #{@log.path}" )
+
+               # set log output
+               builder.log.close
+               builder.log = @log
+
+               # 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     
+
+               # build
+               if @is_remote_job then
+                       result = builder.build(@project.repository, @source_path, @os,
+                               false, @git_commit, @no_reverse, local_pkgs)
+               else
+                       result = builder.build(@source_path, @os, true, local_pkgs, false )
+               end
+               if not result then
+                       @log.error( "Building job failed", Log::LV_USER)
+                       write_log_url()
+                       return false
+               end
+
+               # 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
             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
 
 
-            if dependency_package_exist then 
-                @server.jobmgr.get_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"
-                            @log.info "Enters the PENGING state ..."
-                            while @status == "PENDING" 
-                                sleep 1
-                            end 
-                        end 
-                        break
-                    end 
-                end 
-            end 
+                               sleep 1
+                       end
         end
 
         end
 
-               # remove builder
-               Builder.remove( "builder_#{@id}" )
-               
                return true
        end
 
                return true
        end
 
@@ -362,13 +1051,10 @@ class BuildJob
        
                # get package path list
                binpkg_path_list = Dir.glob("#{@source_path}/*_*_#{@os}.zip")
        
                # 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 )
 
                # 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)
+               snapshot = u_client.upload( @server.pkgserver_addr, @server.pkgserver_port, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd, binpkg_path_list)
 
                if snapshot.nil? then
                        @log.info( "Upload failed...", Log::LV_USER)
 
                if snapshot.nil? then
                        @log.info( "Upload failed...", Log::LV_USER)
@@ -379,46 +1065,157 @@ class BuildJob
                # update local
                @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER)
                @pkgsvr_client.update
                # 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
 
 
                @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)
-               
-               # open
-               client = BuildCommClient.create( server.ip, server.port )
-               if client.nil? then
-                       @status = "ERROR"
-                       return
+       def copy_result_files(dst_path)
+               @log.info( "Copying result files to #{dst_path}", 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
                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)
+       
+               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
                        end
-                       if not result then @status = "ERROR" end
+               else
+                       return nil
                end
                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 { |dep|
+                       new_path = get_local_path_of_dependency(dep, parent)
+                       if not new_path.nil? then
+                               pkg_paths.push new_path
+                       end
+               }
+
+               # 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 { |dep|
+                                       dep_target_os = get_os_of_dependency(dep)
+
+                                       parent.sub_jobs.each { |j| 
+                                               new_deps += j.pkginfo.get_install_dependencies(dep_target_os, dep.package_name)
+                                       }
+                               }
+                               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
 
                end
 
-               return  
+               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
 
        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
 end
index d1d993daeb5b64d4ca6b8d3cb620c9f5f8ecf640..0c7e3c61dfc6264e1406080e40a776a41c9d064b 100644 (file)
@@ -28,36 +28,52 @@ Contributors:
 
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)
 
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)
-$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server"
 require "SocketJobRequestListener.rb"
 require "RemoteBuildJob.rb"
 require "SocketJobRequestListener.rb"
 require "RemoteBuildJob.rb"
-require "LocalBuildJob.rb"
-require "packageServer.rb"
 require "JobManager.rb"
 require "JobManager.rb"
+require "JobClean.rb"
 require "RemoteBuildServer.rb"
 require "RemoteBuildServer.rb"
+require "PackageSync.rb"
+require "ProjectManager.rb"
 
 class BuildServer
 
 class BuildServer
-       attr_accessor :id, :path, :pkgserver_url, :pkgserver_addr, :pkgserver_id, :port, :status, :friend_servers, :host_os, :log
+       attr_accessor :id, :path, :pkgserver_url, :pkgserver_addr, :pkgserver_port, :pkgserver_id, :port, :status, :friend_servers, :host_os, :log
        attr_accessor :git_server_url, :git_bin_path
        attr_accessor :job_log_url
        attr_accessor :allowed_git_branch
        attr_accessor :git_server_url, :git_bin_path
        attr_accessor :job_log_url
        attr_accessor :allowed_git_branch
-       attr_accessor :pkgsvr_cache_path, :local_pkgsvr
        attr_accessor :send_mail
        attr_accessor :jobmgr
        attr_accessor :test_time
        attr_accessor :password
        attr_accessor :finish
        attr_accessor :send_mail
        attr_accessor :jobmgr
        attr_accessor :test_time
        attr_accessor :password
        attr_accessor :finish
+       attr_accessor :build_cache_dir
+       attr_accessor :keep_time
+       attr_accessor :ftp_addr
+       attr_accessor :ftp_port
+       attr_accessor :ftp_username
+       attr_accessor :ftp_passwd
+       attr_accessor :cleaner
+       attr_accessor :prjmgr
+       attr_accessor :transport_path
+       attr_accessor :cancel_lock
+       attr_accessor :supported_os_list
+       attr_accessor :upgrade
+       attr_accessor :remote_pkg_servers
+       attr_accessor :pkg_sync_period
+
        CONFIG_ROOT = "#{Utils::HOME}/.build_tools/build_server"
        HOST_OS = Utils::HOST_OS
 
        # initialize
        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, pkgsvr_url, pkgsvr_addr, pkgsvr_port, pkgsvr_id, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd)
                @id = id
                @path = path
                @id = id
                @path = path
-               @pkgserver_url = pkgserver_url
-               @pkgserver_addr = pkgserver_addr
-               @pkgserver_id = pkgserver_id
+               @pkgserver_url = pkgsvr_url
+               @pkgserver_addr = pkgsvr_addr
+        @pkgserver_port = pkgsvr_port
+               @pkgserver_id = pkgsvr_id
                @friend_servers = []
                @friend_servers = []
+               @remote_pkg_servers = []
                @req_listener = []
                @finish = false
                # port number
                @req_listener = []
                @finish = false
                # port number
@@ -75,11 +91,24 @@ class BuildServer
                @send_mail = "NO"
                # local package server
                @pkgsvr_cache_path = nil
                @send_mail = "NO"
                # 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"
                # Job Manager
                @jobmgr = JobManager.new(self)
                @test_time=0 #test time in mili-seconds
                @password="0000"
+               @keep_time=86400
+        @ftp_addr = ftpsvr_addr
+        @ftp_port = ftpsvr_port
+        @ftp_username = ftpsvr_username
+        @ftp_passwd = ftpsvr_passwd
+               @cleaner=nil
+               @prjmgr = ProjectManager.new(self)
+               # 
+               @transport_path = "#{@path}/transport"
+               @cancel_lock = Mutex.new
+               @supported_os_list = []
+
+               @pkg_sync_period=600
+               @upgrade = false
        end
 
 
        end
 
 
@@ -88,57 +117,74 @@ class BuildServer
                # start
                @log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{@id}/log" )
 
                # start
                @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
 
                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
                # set job request listener
                @log.info "Setting listener..."
                listener2 = SocketJobRequestListener.new(self)
                listener2.start
                @req_listener.push listener2
+
+               # set job cleaner
+               @log.info "Setting Job Cleaner..."
+               @cleaner =  JobCleaner.new(self)
+               @cleaner.start
+
+               # set package server synchrontizer
+               if not @remote_pkg_servers.empty? then
+                       @log.info "Setting Package Server Synchronizer..."
+                       @pkg_sync =  PackageServerSynchronizer.new(self)
+                       @pkg_sync.start
+               end
        
                # main loop
                @log.info "Entering main loop..."
        
                # main loop
                @log.info "Entering main loop..."
-               if @test_time > 0 then start_time = Time.now end
-               while( not @finish )
-
-                       # update friend server status
-                       for server in @friend_servers
-                               # update state
-                               server.update_state
-                       end
-
-                       # handle jobs
-                       @jobmgr.handle()
-
-                       # 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 
+               begin
+                       if @test_time > 0 then start_time = Time.now end
+                       while( not @finish )
+            
+                               # update friend server status
+                               @friend_servers.each do |server|
+                                       # update state
+                                       server.update_state
+                               end
+            
+                               # handle jobs
+                               @jobmgr.handle()
+            
+                               # 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
-                       else
-                               sleep 1
                        end
                        end
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
                end
 
                end
 
+               if(@upgrade)
+                       exit(99)
+               end
                # TODO: something should be done for server down
 
        end
                # TODO: something should be done for server down
 
        end
@@ -152,6 +198,10 @@ class BuildServer
 
        # check the job can be built on this server
        def can_build?(job)
 
        # 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
 
                # check me
                if job.can_be_built_on? @host_os then
@@ -166,39 +216,78 @@ class BuildServer
        def add_remote_server( ip, port )
        
                # if already exit, return false
        def add_remote_server( ip, port )
        
                # if already exit, return false
-               for svr in @friend_servers
+               @friend_servers.each do |svr|
                        if svr.ip.eql? ip and svr.port == port then
                                return false
                        end     
                end
 
                # create new one, and add it into list
                        if svr.ip.eql? ip and svr.port == port then
                                return false
                        end     
                end
 
                # create new one, and add it into list
-               new_server = RemoteBuildServer.new( ip, port )
+               new_server = RemoteBuildServer.new( ip, port, self )
                @friend_servers.push new_server
 
                return true
        end
 
 
                @friend_servers.push new_server
 
                return true
        end
 
 
+       # add new remote pkg server
+       def add_remote_package_server( url, proxy )
+       
+               # if already exit, return false
+               @remote_pkg_servers.each do |entry|
+                       u = entry[0]
+
+                       if u == url then
+                               return false
+                       end
+               end
+
+               @remote_pkg_servers.push [url, proxy]
+
+               return true
+       end
+
+
+       # add new target OS.
+       # If already exist, return false , otherwise true
+       def add_target_os( os_name )
+       
+               # if already exit, return false
+               @supported_os_list.each do |os|
+                       if os.eql? os_name then
+                               return false
+                       end     
+               end
+
+               # add it into list
+               @supported_os_list.push os_name
+
+               return true
+       end
+
+
        # get remote server     
        def get_available_server ( job )
                candidates = []
                
        # get remote server     
        def get_available_server ( job )
                candidates = []
                
-               # check local
-               if @jobmgr.get_number_of_empty_room > 0 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
 
                        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
-                               not server.has_waiting_jobs and 
-                               server.get_number_of_empty_room > 0 )
-                               candidates.push server
+               # get availables server
+               # but, job must not be "REGISTER" and "MULTIBUILD" job
+               if job.type != "REGISTER" and job.type != "MULTIBUILD" then
+                       @friend_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
 
                        end
                end
 
@@ -208,7 +297,7 @@ class BuildServer
                # get best 
                # it is better if working jobs count is less
                max_empty_room = best_server.get_number_of_empty_room
                # get best 
                # it is better if working jobs count is less
                max_empty_room = best_server.get_number_of_empty_room
-               for server in candidates
+               candidates.each do |server|
                        # check whether idle, use it 
                        if not server.has_working_jobs then return server end
 
                        # check whether idle, use it 
                        if not server.has_working_jobs then return server end
 
@@ -234,7 +323,7 @@ class BuildServer
                if can_build? job then return true end
 
                #if not found, check friends
                if can_build? job then return true end
 
                #if not found, check friends
-               for server in @friend_servers
+               @friend_servers.each do |server|
                        if server.status == "RUNNING" and 
                                job.can_be_built_on? server.host_os then
                                return true
                        if server.status == "RUNNING" and 
                                job.can_be_built_on? server.host_os then
                                return true
@@ -261,5 +350,6 @@ class BuildServer
        def has_waiting_jobs
                return @jobmgr.has_waiting_jobs
        end
        def has_waiting_jobs
                return @jobmgr.has_waiting_jobs
        end
+
 end
 
 end
 
index a58734dd76fc3a5ddf3e487cc775ce67b6c2da95..4be6726521b7de1b1a2236447b58ae15dbd508de 100644 (file)
@@ -34,7 +34,7 @@ class BuildServerController
        @@instance_map = {}
 
        # create
        @@instance_map = {}
 
        # create
-       def self.create_server (id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id)
+       def self.create_server (id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_port, pkgsvr_id, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd)
 
                # check server config root
                check_build_server_root
 
                # check server config root
                check_build_server_root
@@ -45,11 +45,11 @@ class BuildServerController
                end
 
                # create new instance and return it
                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, pkgsvr_url, pkgsvr_addr, pkgsvr_port, pkgsvr_id, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd)
                
                # set default
                @@instance_map[id].git_server_url="gerrithost:"
                
                # 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"
                        @@instance_map[id].git_bin_path="/c/Program\\ Files/Git/bin/git.exe"
                else
                        @@instance_map[id].git_bin_path="/usr/bin/git"
@@ -58,7 +58,6 @@ class BuildServerController
                @@instance_map[id].jobmgr.max_working_jobs= 2
                @@instance_map[id].job_log_url=""
                @@instance_map[id].send_mail="NO"
                @@instance_map[id].jobmgr.max_working_jobs= 2
                @@instance_map[id].job_log_url=""
                @@instance_map[id].send_mail="NO"
-               @@instance_map[id].pkgsvr_cache_path="#{path}/pkgsvr_cache"
        
 
                # write config
        
 
                # write config
@@ -79,12 +78,9 @@ class BuildServerController
                        FileUtils.rm_rf "#{BuildServer::CONFIG_ROOT}/#{id}"
                        @@instance_map[id] = nil
                        puts "Removed the server \"#{id}\""
                        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
                end
-               
-               # remove local package server
-               local_pkgsvr = PackageServer.new( id )
-               local_pkgsvr.remove_server(id)  
-
        end
 
 
        end
 
 
@@ -98,7 +94,7 @@ class BuildServerController
 
                # check server config 
                if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{id}/server.cfg" 
 
                # check server config 
                if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{id}/server.cfg" 
-                       raise RuntimeError, "The server \"#{id}\" does not exist."
+                       raise RuntimeError, "The server \"#{id}\" does not exist!"
                end
 
                # get server config and return its object
                end
 
                # get server config and return its object
@@ -137,7 +133,7 @@ class BuildServerController
 
                # send request
                stop_ok = false
 
                # send request
                stop_ok = false
-               if client.send "STOP,#{server.password}" then
+               if client.send "STOP|#{server.password}" then
                        # recevie & print
                        mismatched = false
                        result = client.read_lines do |l|
                        # recevie & print
                        mismatched = false
                        result = client.read_lines do |l|
@@ -161,6 +157,94 @@ class BuildServerController
                return true
        end
 
                return true
        end
 
+       # upgrade server
+       def self.upgrade_server( id )
+
+               # server
+               server = get_server(id)
+               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)
+               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
+       
+                                       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 |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 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             
+               
+               return true
+       end
+
 
        # add friend server
        def self.add_friend_server( id, ip, port )
 
        # add friend server
        def self.add_friend_server( id, ip, port )
@@ -185,82 +269,210 @@ class BuildServerController
        end
 
 
        end
 
 
-       # build git repository and upload
-       def self.build_git( id, repository, commit, os, url, resolve )
-
-               # server
+       # add remote package server
+       def self.add_remote_package_server(id, url, proxy )
                server = get_server(id)
                server = get_server(id)
-               client = BuildCommClient.create( "127.0.0.1", server.port )
-               if client.nil? then return false end
+               
+               # add
+               if server.add_remote_package_server( url, proxy ) then
 
 
-               # send request
-               client.send "BUILD,GIT,#{repository},#{commit},#{os}"
+                       # write config  
+                       server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}"
+                       f = File.open( "#{server_dir}/remote_pkg_servers", "a" )
+                       if not proxy.nil? then
+                               f.puts "#{url}|#{proxy}"
+                       else
+                               f.puts "#{url}|"
+                       end
+                       f.close 
+                       
+                       puts "Remote package server is added!"
+                       
+                       return true
+               else
+                       puts "The server already exists in list!"
 
 
-               # recevie & print
-               client.print_stream
+                       return false
+               end
+       end
 
 
-               # terminate     
-               client.terminate
 
 
-               return true
+       # add supported target os
+       def self.add_target_os( id, os_name )
+               # TODO:check os foramt
+               if os_name == "default" then
+                       puts "Cannot use \"default\" as target OS name!"
+                       return false
+               end
+
+               # get server
+               server = get_server(id)
+               
+               # add
+               if server.add_target_os( os_name ) then
+
+                       # write config  
+                       server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}"
+                       f = File.open( "#{server_dir}/supported_os_list", "a" )
+                       f.puts "#{os_name}"
+                       f.close 
+                       
+                       puts "Target OS is added successfully!"
+                       
+                       return true
+               else
+                       puts "Target OS already exists in list!"
+                       return false
+               end
        end
 
 
        end
 
 
-       # resolve git and build it and upload 
-       def resolve_git( id, repository, commit, os, url )
-               # server
+       # add project
+       def self.add_project( id, project_name, git_repos, git_branch, remote_server_id, passwd, os_string )
+               # get server
                server = get_server(id)
                server = get_server(id)
-               client = BuildCommClient.create( "127.0.0.1", server.port )
-               if client.nil? then return false end
+       
+               # 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(",")
+               end     
+
+               # 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
 
 
-               # send request
-               client.send "RESOLVE,GIT,#{repository},#{commit},#{os}" 
+                               return false
+                       end
+               end
 
 
-               # recevie & print
-               client.print_stream
+               # add
+               if not git_repos.nil? and not git_branch.nil? then
+                       result = server.prjmgr.add_git_project( project_name, git_repos, git_branch, passwd, os_list )
+               elsif not remote_server_id.nil? then
+                       result = server.prjmgr.add_remote_project( project_name, remote_server_id, passwd, os_list)
+               else
+                       result = false  
+               end
+                       
+               if result then
+                       puts "Adding project succeeded!"
+                       return true
+               else
+                       puts "Adding project failed!"
+                       return false
+               end
+       end
 
 
-               # terminate     
-               client.terminate
 
 
-               return true
+       # add binary project
+       def self.add_binary_project( id, project_name, pkg_name, passwd, os_string )
+               # get server
+               server = get_server(id)
+       
+               # 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(",")
+               end     
+
+               # add
+               result = server.prjmgr.add_binary_project( project_name, pkg_name, passwd, os_list )
+                       
+               if result then
+                       puts "Adding project succeeded!"
+                       return true
+               else
+                       puts "Adding project failed!"
+                       return false
+               end
        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 )
+
                # server
                server = get_server(id)
                client = BuildCommClient.create( "127.0.0.1", server.port )
                # server
                server = get_server(id)
                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
 
                # send request
-               client.send "BUILD,LOCAL,#{local_path},#{os}"
-
-               # recevie & print
-               client.print_stream
+               fullbuild_ok = false
+               if client.send "FULLBUILD|#{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
+                               fullbuild_ok = true
+                       end
+               end
 
                # terminate     
                client.terminate
 
                # terminate     
                client.terminate
+       
+               if not fullbuild_ok then        
+                       puts "Full build failed!"
+               end
 
                return true
        end
 
 
 
                return true
        end
 
 
-       # resolve local project and  build it and upload
-       def resolve_local( path, os )
+       def self.register_package(id, file_path)
                # server
                server = get_server(id)
                client = BuildCommClient.create( "127.0.0.1", server.port )
                # server
                server = get_server(id)
                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 "RESOLVE,LOCAL,#{local_path},#{os}"
+               if not File.exist? file_path then
+                       puts "File not found!"
+                       return false
+               end
 
 
-               # recevie & print
-               client.print_stream
+               file_path = File.expand_path(file_path)
+               # send request
+               success = false
+               if client.send "REGISTER|BINARY-LOCAL|#{file_path}|#{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
+                               success = true
+                       end
+               end
 
                # terminate     
                client.terminate
 
                # terminate     
                client.terminate
+       
+               if not success then     
+                       puts "Registering package failed!"
+               end
 
                return true
        end
 
                return true
        end
@@ -281,7 +493,9 @@ class BuildServerController
        def self.write_server_config( server )
                # create config folder
                server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}"
        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|
 
                # write configuration
                File.open( "#{server_dir}/server.cfg", "w" ) do |f|
@@ -289,8 +503,8 @@ class BuildServerController
                        f.puts "PATH=#{server.path}"
                        f.puts "PSERVER_URL=#{server.pkgserver_url}"
                        f.puts "PSERVER_ADDR=#{server.pkgserver_addr}"
                        f.puts "PATH=#{server.path}"
                        f.puts "PSERVER_URL=#{server.pkgserver_url}"
                        f.puts "PSERVER_ADDR=#{server.pkgserver_addr}"
+            f.puts "PSERVER_PORT=#{server.pkgserver_port}"
                        f.puts "PSERVER_ID=#{server.pkgserver_id}"
                        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 "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}"
@@ -299,6 +513,12 @@ class BuildServerController
                        f.puts "SEND_MAIL=#{server.send_mail}"
                        f.puts "TEST_TIME=#{server.test_time}" if server.test_time > 0
                        f.puts "PASSWORD=#{server.test_time}" if server.password != "0000"
                        f.puts "SEND_MAIL=#{server.send_mail}"
                        f.puts "TEST_TIME=#{server.test_time}" if server.test_time > 0
                        f.puts "PASSWORD=#{server.test_time}" if server.password != "0000"
+                       f.puts "JOB_KEEP_TIME=#{server.keep_time}"
+                       f.puts "FTP_ADDR=#{server.ftp_addr}"
+            f.puts "FTP_PORT=#{server.ftp_port}"            
+                       f.puts "FTP_USERNAME=#{server.ftp_username}"
+                       f.puts "FTP_PASSWD=#{server.ftp_passwd}"
+                       f.puts "PKG_SYNC_PERIOD=#{server.pkg_sync_period}"
                end
        end
 
                end
        end
 
@@ -308,8 +528,8 @@ class BuildServerController
                path=""
                pkgsvr_url=""
                pkgsvr_addr=""
                path=""
                pkgsvr_url=""
                pkgsvr_addr=""
+        pkgsvr_port="3333"
                pkgsvr_id=""
                pkgsvr_id=""
-               pkgsvr_cache_path=""
                git_server_url="gerrithost:"
                git_bin_path="/usr/bin/git"
                allowed_git_branch=""
                git_server_url="gerrithost:"
                git_bin_path="/usr/bin/git"
                allowed_git_branch=""
@@ -318,6 +538,12 @@ class BuildServerController
                send_mail="NO"
                test_time=0
                password="0000"
                send_mail="NO"
                test_time=0
                password="0000"
+               keep_time=86400
+               ftp_addr=""
+               ftp_port="21"
+               ftp_username=""
+               ftp_passwd=""
+               pkg_sync_period=600             
 
                # read configuration
                server_dir = "#{BuildServer::CONFIG_ROOT}/#{id}"
 
                # read configuration
                server_dir = "#{BuildServer::CONFIG_ROOT}/#{id}"
@@ -332,10 +558,10 @@ class BuildServerController
                                        pkgsvr_url = l[idx,length].strip
                                elsif l.start_with?("PSERVER_ADDR=")
                                        pkgsvr_addr = l[idx,length].strip
                                        pkgsvr_url = l[idx,length].strip
                                elsif l.start_with?("PSERVER_ADDR=")
                                        pkgsvr_addr = l[idx,length].strip
+                               elsif l.start_with?("PSERVER_PORT=")
+                                       pkgsvr_port = l[idx,length].strip
                                elsif l.start_with?("PSERVER_ID=")
                                        pkgsvr_id = l[idx,length].strip
                                elsif l.start_with?("PSERVER_ID=")
                                        pkgsvr_id = l[idx,length].strip
-                               elsif l.start_with?("PSERVER_CACHE_PATH=")
-                                       pkgsvr_cache_path = l[idx,length].strip
                                elsif l.start_with?("GIT_SERVER_URL=")
                                        git_server_url = l[idx,length].strip
                                elsif l.start_with?("GIT_BIN_PATH=")
                                elsif l.start_with?("GIT_SERVER_URL=")
                                        git_server_url = l[idx,length].strip
                                elsif l.start_with?("GIT_BIN_PATH=")
@@ -352,6 +578,18 @@ class BuildServerController
                                        test_time = l[idx,length].strip.to_i
                                elsif l.start_with?("PASSWORD=")
                                        password = l[idx,length].strip.to_i
                                        test_time = l[idx,length].strip.to_i
                                elsif l.start_with?("PASSWORD=")
                                        password = l[idx,length].strip.to_i
+                               elsif l.start_with?("JOB_KEEP_TIME=")
+                                       keep_time = l[idx,length].strip.to_i
+                               elsif l.start_with?("FTP_ADDR=")
+                                       ftp_addr = l[idx,length].strip
+                               elsif l.start_with?("FTP_PORT=")
+                                       ftp_port = l[idx,length].strip
+                               elsif l.start_with?("FTP_USERNAME=")
+                                       ftp_username = l[idx,length].strip
+                               elsif l.start_with?("FTP_PASSWD=")
+                                       ftp_passwd = l[idx,length].strip
+                               elsif l.start_with?("PKG_SYNC_PERIOD=")
+                                       pkg_sync_period = l[idx,length].strip.to_i
                                else
                                        next    
                                end 
                                else
                                        next    
                                end 
@@ -359,7 +597,7 @@ class BuildServerController
                end
 
                # create server object
                end
 
                # create server object
-               obj = BuildServer.new( id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id )
+               obj = BuildServer.new( id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_port, pkgsvr_id, ftp_addr, ftp_port, ftp_username, ftp_passwd )
 
                # check running port
                if File.exist? "#{server_dir}/run" then
 
                # check running port
                if File.exist? "#{server_dir}/run" then
@@ -381,6 +619,28 @@ class BuildServerController
                        end
                end             
 
                        end
                end             
 
+               # check remote package server
+               if File.exist? "#{server_dir}/remote_pkg_servers" then
+                       File.open( "#{server_dir}/remote_pkg_servers", "r" ) do |f|
+                               f.each_line do |l|
+                                       if l.split("|").count < 2 then next end
+                                       url = l.split("|")[0].strip
+                                       proxy = l.split("|")[1].strip
+                                       obj.add_remote_package_server( url, proxy )
+                               end
+                       end
+               end
+               
+               # check supported os
+               if File.exist? "#{server_dir}/supported_os_list" then
+                       File.open( "#{server_dir}/supported_os_list", "r" ) do |f|
+                               f.each_line do |l|
+                                       os_name = l.strip
+                                       obj.add_target_os( os_name )
+                               end
+                       end
+               end     
+       
                # set git server url
                obj.git_server_url = git_server_url
 
                # set git server url
                obj.git_server_url = git_server_url
 
@@ -399,16 +659,24 @@ class BuildServerController
                # set allowed git branch name
                obj.allowed_git_branch = allowed_git_branch
 
                # set allowed git branch name
                obj.allowed_git_branch = allowed_git_branch
 
-               # set package server path
-               pkgsvr_cache_path = (pkgsvr_cache_path.empty? ? "#{path}/pkgsvr_cache":pkgsvr_cache_path)
-               obj.pkgsvr_cache_path= pkgsvr_cache_path
-
                # set test time 
                obj.test_time = test_time
 
                # set password
                obj.password = password
 
                # set test time 
                obj.test_time = test_time
 
                # set password
                obj.password = password
 
+               # set password
+               obj.keep_time = keep_time
+
+               # set ftp infomation
+               obj.ftp_addr = ftp_addr
+        obj.ftp_port = ftp_port
+               obj.ftp_username = ftp_username
+               obj.ftp_passwd = ftp_passwd
+
+               # pkg synchronization
+               obj.pkg_sync_period = pkg_sync_period
+
                # save config
                write_server_config( obj )
                
                # save config
                write_server_config( obj )
                
index f14f69c05093c17f5b3b58113430795129655ab9..4c1ba9a2707f69e9b4a3ea56c677fdb324962186 100644 (file)
@@ -26,56 +26,192 @@ Contributors:
 - S-Core Co., Ltd
 =end
 
 - S-Core Co., Ltd
 =end
 
+$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 require 'optparse'
 require 'optparse'
+require 'utils'
+
+def option_error_check( options )
+    case options[:cmd]
+
+    when "create"
+        if options[:name].nil? or options[:name].empty? or 
+            options[:url].nil? or options[:url].empty? or
+            options[:domain].nil? or options[:domain].empty? or
+            options[:fdomain].nil? or options[:fdomain].empty? then
+            raise ArgumentError, "Usage: build-svr create -n <server name> -u <package server url> -d <package server address> -t <ftp server url>"
+        end            
+
+    when "remove"
+        if options[:name].nil? or options[:name].empty? then 
+            raise ArgumentError, "Usage: build-svr remove -n <server name>"
+        end
+
+    when "start"
+        if options[:name].nil? or options[:name].empty? or
+                options[:port].nil? then
+            raise ArgumentError, "Usage: build-svr start -n <server name> -p <port>"
+        end
+
+    when "stop"
+        if options[:name].nil? or options[:name].empty? then
+            raise ArgumentError, "Usage: build-svr stop -n <server name>"
+        end
+
+    when "upgrade"
+        if options[:name].nil? or options[:name].empty? then
+            raise ArgumentError, "Usage: build-svr upgrade -n <server name>"
+        end
+
+    when "add-svr"
+        if options[:name].nil? or options[:name].empty? or 
+                       ((options[:domain].nil? or options[:domain].empty?) and
+                        (options[:url].nil? or options[:url].empty?)) then
+            raise ArgumentError, "Usage: build-svr add-svr -n <server name> (-d <friend server address>|-u <remote pkg server url>)  [--proxy <proxy url>]"
+        end
+
+    when "add-prj"
+        if options[:name].nil? or options[:name].empty? or
+            options[:pid].nil? or options[:pid].empty? then
+            raise ArgumentError, "Usage: build-svr add-prj -n <server name> -N <project name> (-g <git repository> -b <git branch>|-P <package name>) [-w <password>] [-o <os list>]"
+        end  
+
+    when "add-os"
+        if options[:name].nil? or options[:name].empty? or
+            options[:os].nil? or options[:os].empty? then
+            raise ArgumentError, "Usage: build-svr add-os -n <server name> -o <os>"
+        end  
+
+    when "fullbuild"
+        if options[:name].nil? or options[:name].empty? then
+            raise ArgumentError, "Usage: build-svr fullbuild -n <server name>"
+        end
+
+    when "register"
+        if options[:name].nil? or options[:name].empty? or
+                       options[:package].nil? or options[:package].empty?  then
+            raise ArgumentError, "Usage: build-svr register -n <server name> -P <package file>"
+        end
+    else
+        raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
+    end            
+end
 
 def option_parse 
     options = {}
 
 def option_parse 
     options = {}
-    banner = "Usage: build-svr {create|remove|start|build|help} ..." + "\n" \
-        + "\t" + "build-svr create -n <name> -u <pkg-server-url> -d <pkg-server-domain> -i <pkg-server-id>" + "\n" \
-        + "\t" + "build-svr remove -n <name>" + "\n" \
-        + "\t" + "build-svr start -n <name> [-p <port]" + "\n" \
-        + "\t" + "build-svr stop -n <name> " + "\n" \
-        + "\t" + "build-svr add -n <name> [-d <frined-svr-domain> -p <friend-svr port>]" + "\n" 
-
-    optparse = OptionParser.new do|opts|
+    banner = "Build-server administer service command-line tool." + "\n" \
+       + "\n" + "Usage: build-svr <SUBCOMMAND> [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" + "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" + "add-prj       Register information for project what you want build berfore building a 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" \
+       + "\n" + "Subcommand usage:" + "\n" \
+        + "\t" + "build-svr create -n <server name> -u <package server url> -d <package server address> -t <ftp server url>" + "\n" \
+        + "\t" + "build-svr remove -n <server name>" + "\n" \
+        + "\t" + "build-svr start -n <server name> -p <port>" + "\n" \
+        + "\t" + "build-svr stop -n <server name>" + "\n" \
+        + "\t" + "build-svr upgrade -n <server name>" + "\n" \
+        + "\t" + "build-svr add-svr -n <server name> (-d <friend server address>|-u <remote pkg server url>)  [--proxy <proxy url>]" + "\n" \
+        + "\t" + "build-svr add-prj -n <server name> -N <project name> (-g <git repository> -b <git branch>|-P <package name>) [-w <password>] [-o <os list>]" + "\n" \
+        + "\t" + "build-svr add-os -n <server name> -o <os>" + "\n" \
+        + "\t" + "build-svr register -n <server name> -P <package file>" + "\n" \
+        + "\t" + "build-svr fullbuild -n <server name>" + "\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 
 
         # Set a banner, displayed at the top
         # of the help screen.
 
                opts.banner = banner 
 
-        opts.on( '-n', '--name <name>', 'build server name' ) do|name|
+        opts.on( '-n', '--name <server name>', 'build server name' ) do|name|
             options[:name] = name 
         end
         
             options[:name] = name 
         end
         
-               opts.on( '-u', '--url <pkg-server-url>', 'package server URL: http://xxx/yyy/zzz' ) do|url|
+               opts.on( '-u', '--url <package server url>', 'package server url: http://127.0.0.1/dibs/unstable' ) do|url|
             options[:url] = url 
         end
 
             options[:url] = url 
         end
 
-               opts.on( '-d', '--domain <pkg/friend-svr domain>', 'package svr or friend svr ip or ssh alias' ) do|domain|
+        options[:proxy] = nil
+               opts.on( '--proxy <proxy url>', 'proxy url: http://172.21.111.100:2222' ) do|proxy|
+            options[:proxy] = proxy
+        end
+
+               opts.on( '-d', '--address <server address>', 'server address: 127.0.0.1:2224' ) do|domain|
             options[:domain] = domain
         end
                
             options[:domain] = domain
         end
                
-               opts.on( '-i', '--id <pkg-server-id>', 'package server id' ) do|pid|
+        options[:port] = 2222
+               opts.on( '-p', '--port <port>', 'server port number: 2224' ) do|port|
+            options[:port] = port.strip.to_i
+        end
+
+               opts.on( '-P', '--pkg <package name/file>', 'package file path or name' ) do|package|
+            options[:package] = package.strip
+        end
+
+        options[:os] = nil
+               opts.on( '-o', '--os <target os list>', '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>', 'project name' ) do|pid|
             options[:pid] = pid
         end
 
             options[:pid] = pid
         end
 
-        options[:port] = 2222
-               opts.on( '-p', '--port <port>', 'port' ) do|port|
-            options[:port] = port.strip.to_i
+               opts.on( '-g', '--git <git repository>', 'git repository' ) do|git|
+            options[:git] = git
+        end
+
+               opts.on( '-b', '--branch <git branch>', 'git branch' ) do|branch|
+            options[:branch] = branch
+        end
+
+               #opts.on( '-r', '--remote <remote server id>', 'remote server id' ) do|remote|
+        #    options[:remote] = remote
+        #end
+
+        options[:passwd] = ""
+               opts.on( '-w', '--passwd <password>', 'password for managing project' ) do|passwd|
+            options[:passwd] = passwd
+        end
+
+               opts.on( '-t', '--ftp <ftp server url>', 'ftp server url: ftp://dibsftp:dibsftp@127.0.0.1:1024' ) do|domain|
+            options[:fdomain] = domain
         end
                
                opts.on( '-h', '--help', 'display this information' ) do
         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
                        exit
         end
+
+               opts.on( '-C', '--CHILD', 'child process' ) do
+            options[:child] = true
+        end
                
     end
     
        cmd = ARGV[0] 
                
     end
     
        cmd = ARGV[0] 
-
-    if cmd.eql? "create" or cmd.eql? "remove" or cmd.eql? "start" or 
-               cmd.eql? "stop" or cmd.eql? "add" or
-                cmd =~ /(help)|(-h)|(--help)/ then
+    if cmd.eql? "create" or cmd.eql? "remove" or 
+               cmd.eql? "start" or cmd.eql? "upgrade" or
+               cmd.eql? "stop" or cmd.eql? "add-svr" or
+               cmd.eql? "add-prj" or cmd.eql? "add-os" or 
+               cmd.eql? "fullbuild" or cmd.eql? "register" or 
+        cmd =~ /(-v)|(--version)/ or        
+        cmd =~ /(help)|(-h)|(--help)/ then
 
         if cmd.eql? "help" then 
                        ARGV[0] = "-h" 
 
         if cmd.eql? "help" then 
                        ARGV[0] = "-h" 
@@ -83,10 +219,12 @@ def option_parse
 
         options[:cmd] = ARGV[0]
     else
 
         options[:cmd] = ARGV[0]
     else
-        raise ArgumentError, banner
+        raise ArgumentError, "Usage: build-svr <SUBCOMMAND> [OPTS] or build-svr -h" 
     end
 
     optparse.parse!
     end
 
     optparse.parse!
+
+    option_error_check options
    
     return options
 end 
    
     return options
 end 
diff --git a/src/build_server/CommonProject.rb b/src/build_server/CommonProject.rb
new file mode 100644 (file)
index 0000000..10caaaf
--- /dev/null
@@ -0,0 +1,102 @@
+=begin
+ CommonProject.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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
+
+       # initialize
+       def initialize( name, type, server, os_list )
+               @name = name
+               @type = type
+               @passwd = ""
+               @os_list = os_list
+               @server = server
+               @extra_infos = {}
+               read_ext_info
+       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 write_ext_info
+               # write to file
+               info_file = "#{@server.path}/projects/#{@name}/extra"
+               File.open( info_file, "w" ) do |f|
+                       @extra_infos.each { |key,value|
+                               f.puts "#{key} : #{value}"
+                       }
+               end
+       end
+
+
+       # set extra info
+       def read_ext_info
+               info_file = "#{@server.path}/projects/#{@name}/extra"
+               if not File.exists? info_file then return end
+               File.open( info_file, "r" ) do |f|
+                       while (not f.gets and line = f.gets.split(":"))
+                               if not line[1].nil? then
+                                       @extra_infos[line[0].strip] = line[1].strip
+                               end
+                       end
+               end
+       end
+
+
+       def set_log_cnt( cnt )
+               @extra_infos["Latest_log_count"] = cnt.to_s
+       end
+
+
+       def get_latest_log_cnt
+               result = @extra_infos["Latest_log_count"]
+               if not result.nil? then
+                       return result.to_i
+               end
+               return nil
+       end
+end
diff --git a/src/build_server/FullBuildJob.rb b/src/build_server/FullBuildJob.rb
new file mode 100644 (file)
index 0000000..5c83fee
--- /dev/null
@@ -0,0 +1,255 @@
+=begin
+
+ FullBuildJob.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "BuildServer.rb"
+require "JobLog.rb"
+require "mail.rb"
+
+class FullBuildJob
+
+       attr_accessor :id, :server, :pre_jobs, :os, :type
+       attr_accessor :status, :log, :source_path
+       attr_accessor :pkgsvr_client, :thread
+       attr_accessor :is_fullbuild_job
+
+       # initialize
+       def initialize (server)
+               @server = server
+               @id = server.jobmgr.get_new_job_id()
+               @log = nil
+               @type = "FULLBUILD"
+
+               @status = "JUST_CREATED"
+               @host_os = Utils::HOST_OS
+               @pkgserver_url = @server.pkgserver_url
+               @job_root = "#{@server.path}/jobs/#{@id}"
+               @source_path = @job_root+"/temp"
+               @job_working_dir=@job_root+"/works"
+               @buildroot_dir = "#{@job_root}/buildroot"
+               @pre_jobs = [] #pre-requisite jobs
+
+               @is_fullbuild_job = false
+       end
+
+
+       # execute
+       def execute(sync=false)
+               @log.info( "Invoking a thread for FULL-BUILD Job #{@id}", Log::LV_USER)
+               if @status == "ERROR" then return  end
+               @thread = Thread.new {
+                       begin
+                               thread_main()
+                               terminate()
+                       rescue => e
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                       end
+               }
+
+               if sync then
+                       @thread.join
+               end
+               
+               return true      
+       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 dummy source path
+               if not File.exist? @source_path then
+                       FileUtils.mkdir_p @source_path
+               end 
+
+               # set up pkgsvr_client
+               @pkgsvr_client =  Client.new(@pkgserver_url, @job_working_dir, @log)
+               @pkgsvr_client.update
+               
+               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
+                       # clean up
+                       @server.cleaner.clean(@id)
+               end
+
+               # close logger
+               @log.close
+       end
+
+
+       #cancel
+       def cancel()
+               #TODO
+       end
+
+
+       # check building is possible
+       def can_be_built_on?(host_os)
+               return true
+       end
+
+
+       def has_build_dependency?(other_job)
+               return true
+       end
+
+
+       def has_same_packages?( wjob )
+               return self.eql? wjob
+       end
+
+
+       def does_depend_on?( wjob )
+               return true
+       end
+
+
+       def does_depended_by?( wjob )
+               return true
+       end
+
+
+       def is_connected?
+               return true
+       end
+
+
+       # return the job is asyncronous job
+       def is_asynchronous_job?
+               return false
+       end
+
+       # set logger 
+       def set_logger( logger )
+               @log =  logger
+       end
+
+
+       #
+       # PROTECTED METHODS
+       #
+       protected
+
+
+       # main module   
+       def thread_main
+               @log.info( "New Job #{@id} is started", Log::LV_USER)
+               
+               # check passwd
+
+               # create sub jobs
+               build_jobs = []
+               @server.prjmgr.projects.each do |prj|
+                       if prj.type != "GIT" then next end      
+                       build_jobs += @server.prjmgr.create_new_jobs_for_all_os( prj.name )
+               end
+       
+               # set full build job flag
+               build_jobs.each do |job|
+                       job.is_fullbuild_job = true
+                       job.set_parent_job( self )
+               end
+
+               # add all jobs to jobmanager
+               job_status_map = {} # for tracking job status changes
+               build_jobs.each do |job|
+                       @server.jobmgr.add_internal_job( job )
+
+                       @log.info( "Added new job \"#{job.id}\"(#{job.get_project().name}) for #{job.os}!",
+                                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
+
+                       # set satus
+                       job_status_map[job.id] = job.status
+               end
+
+               # show job status changes
+               all_jobs_finished = false
+               error_exist = false
+               while not all_jobs_finished
+                       all_jobs_finished = true
+                       build_jobs.each do |job|
+
+                               # check status chanaged, if then print
+                               if job_status_map[ job.id ]  != job.status then
+                                       @log.info("Job #{job.id}(#{job.get_project().name},#{job.os}) is #{job.status}", Log::LV_USER)
+                                       job_status_map[ job.id ] = job.status
+                               end
+                               if job.status != "ERROR" and job.status != "FINISHED" then
+                                       all_jobs_finished = false
+                               end
+                               if job.status == "ERROR" then error_exist = true end
+                       end
+                       sleep 1
+               end
+
+               # check error
+               if error_exist then 
+                       @status = "ERROR"
+                       return
+               end
+
+               # INFO. don't change this string
+               @log.info( "Job is completed!", Log::LV_USER)
+               @status = "FINISHED"
+       end
+
+end
index 75fc50285801719e9ab40b0f976486b734138847..5b1b696e857e92f93c9fd09981bb0beffa10cf07 100644 (file)
@@ -27,194 +27,159 @@ Contributors:
 =end
 
 require "fileutils"
 =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"
 
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "BuildJob.rb"
 require "utils.rb"
 
+
 class GitBuildJob < BuildJob
 class GitBuildJob < BuildJob
-       attr_accessor :id, :status, :pkginfo, :pkgsvr_client, :thread, :log, :rev_fail_list, :rev_success_list, :source_path
 
        # initialize
 
        # initialize
-       def initialize ( repos, commit, os, pkgsvr_url, options, server, parent, outstream, resolve)
-               super()
-        @rev_fail_list = []
-        @rev_success_list = []
-               @id = server.jobmgr.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(server.jobmgr.get_new_job_id(), project, os, server)
+               @git_repos = project.repository
+               @git_branch = project.branch
+               @git_commit = nil
        end
 
 
        def terminate()
        end
 
 
        def terminate()
-
                # report error
                if @status == "ERROR" then
                        @log.error( "Job is stopped by ERROR" , Log::LV_USER)
                # 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
+                       @log.error( "Job is CANCELED" , Log::LV_USER)
+                       @server.cleaner.clean_afterwards(@id)
                else
                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.add_source_info( @pkginfo.get_version(), @git_commit)
+                       @project.copy_package_info( @pkginfo.get_version(), 
+                               "#{@source_path}/package/pkginfo.manifest")
+                       @project.set_log_cnt( @log.cnt )
+                       @project.write_ext_info
+
+                       # 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 ( @server.send_mail.eql? "YES" ) and ( not @pkginfo.nil? ) and ( not @pkginfo.packages.nil? ) then 
                        mail_list = []
                        contents = []
                end
 
                # 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 "---------------------------------------------------------------"
                        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  
+                       @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 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"
                                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
                        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 
+               end
 
                # close logger
                @log.close
 
                # close logger
                @log.close
-
-               # 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 )
-               end
        end
 
 
        # verify
        end
 
 
        # verify
-       def pre_verify
-               @log.info( "Verifying job input...", Log::LV_USER)
+       def init
+               # mkdir job root
+               if not File.exist? @job_root then FileUtils.mkdir_p @job_root 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)
-                       @status = "ERROR"
-                       return false
+               # create logger
+               if @log.nil? then
+                       @log = JobLog.new(self, nil )
                end
 
                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)
-                       @status = "ERROR"
-                       return false
-               end
+               @log.info( "Initializing job...", Log::LV_USER)
 
 
-               # 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
-                       end
+               # 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" 
 
 
-                       if not is_correct_branch then
-                               @log.error( "Wrong branch is used! Check your commit-id again", Log::LV_USER)
-                               @status = "ERROR"
-                               return false
+                       incoming_dir = "#{@server.transport_path}/#{@dock_num}"
+                       if File.exist? incoming_dir then
+                               FileUtils.mv "#{incoming_dir}", "#{ext_pkgs_dir}"
                        end
                        end
+
+                       FileUtils.mkdir_p incoming_dir
+               end
+
+               # download source code
+               @git_commit = @project.get_source_code(@git_repos, @git_branch, @git_commit, @source_path, @log)
+               if @git_commit.nil? then
+                       @status = "ERROR"
+                       return false
                end
                end
-               
 
                # check pkginfo.manifest
                if not File.exist? "#{@source_path}/package/pkginfo.manifest"
 
                # check pkginfo.manifest
                if not File.exist? "#{@source_path}/package/pkginfo.manifest"
-                       @log.error( "package/pkginfo.manifest doest not exist", Log::LV_USER)
+                       @log.error( "package/pkginfo.manifest does not exist", Log::LV_USER)
                        @status = "ERROR"
                        return false
                end
 
                # set up pkg info
                        @status = "ERROR"
                        return false
                end
 
                # set up pkg info
+               begin
                @pkginfo = PackageManifest.new("#{@source_path}/package/pkginfo.manifest")
                @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(@pkgserver_url, @job_working_dir, @log)
 
                # set up pkgsvr_client
                @pkgsvr_client =  Client.new(@pkgserver_url, @job_working_dir, @log)
-               @pkgsvr_client.update
 
 
-               return true
-       end
+               # 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 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
 
 
-    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
+               return true
        end
 
 
        end
 
 
-    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
+       def set_git_commit( commit )
+               @git_commit = commit
        end
 
        end
 
+
 end
 end
diff --git a/src/build_server/GitBuildProject.rb b/src/build_server/GitBuildProject.rb
new file mode 100644 (file)
index 0000000..d06af21
--- /dev/null
@@ -0,0 +1,264 @@
+=begin
+ GitProject.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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__)
+require "CommonProject.rb"
+require "GitBuildJob.rb"
+require "Version.rb"
+require "PackageManifest.rb"
+
+# mutax for git operation
+$git_mutex = Mutex.new
+
+
+class GitBuildProject < CommonProject
+       attr_accessor :repository, :branch
+
+       # initialize
+       def initialize( name, repos, branch, server, os_list )
+               super(name, "GIT", server, os_list)
+               @repository = repos 
+               @branch = branch
+               @source_infos = {}
+               @package_infos = {}
+       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.set_git_commit( commit )
+               end
+               
+               return new_job
+       end
+
+       # get latest package version 
+       def get_latest_version()
+               versions = @package_infos.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_infos.keys
+       end
+
+
+       # add source source info
+       def add_source_info( version, info )
+               @source_infos[version] =  info
+
+               # write to file
+               sources_file = "#{@server.path}/projects/#{@name}/sources"
+               File.open( sources_file, "w" ) do |f|
+                       @source_infos.each { |key,value|
+                               f.puts "#{key},#{value}"
+                       }
+               end
+       end
+
+
+       # get source info
+       def get_source_info( version )
+               return @source_infos[version]
+       end
+
+
+       # add package info
+       def add_package_info( version, path )
+               begin
+               pkginfo =PackageManifest.new(path)
+               rescue => e
+                       puts e.message
+                       return
+               end
+               @package_infos[version] =  pkginfo
+       end
+
+
+       # get package info
+       def get_package_info( version )
+               return @package_infos[version]
+       end
+
+
+       # copy package info
+       def copy_package_info(version, file_path)
+               # check pkginfo directory
+               pkginfo_dir = "#{@server.path}/projects/#{@name}/pkginfos"
+               if not File.exist? pkginfo_dir then
+                       FileUtils.mkdir_p pkginfo_dir
+               end
+
+               # copy
+               pkginfo_file = "#{pkginfo_dir}/#{version}.manifest"
+               FileUtils.cp(file_path, pkginfo_file)
+
+               add_package_info(version,  pkginfo_file)
+       end
+
+
+       def include_package?(name, version=nil, os=nil)
+               # check version first
+               if not version.nil? then
+                       version = get_latest_version()
+               end
+
+               if version.nil? or @package_infos[version].nil? then return false end
+
+               # check supported os
+               if not os.nil? and not @os_list.include? os then return false end
+
+               # check name and version
+               pkginfo=@package_infos[version]
+               pkg_list = os.nil? ? pkginfo.packages : pkginfo.get_target_packages(os)
+               pkg_list.each do |pkg|
+                       if pkg.package_name.eql? name  then return true end
+               end
+               
+               return false
+       end
+
+
+       # download source code to "source_path" and return its commit-id
+       def get_source_code( git_repos, git_branch, git_commit, source_path, log )
+               $git_mutex.synchronize {
+                       # check git directory
+                       git_path = "#{@server.path}/projects/#{@name}/cache/git"
+                       cache_path = "#{@server.path}/projects/#{@name}/cache"
+                       if not File.exist? cache_path then
+                               FileUtils.mkdir_p cache_path
+                       end
+               
+                       # check branch name
+                       if File.exist? git_path then
+                               current_branch =  git_cmd_return( "branch",  git_path).select{|x| x.start_with?("*")}[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
+
+                       # 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
+                       FileUtils.cp_r(git_path, source_path)
+               }
+
+               return git_commit
+       end
+
+
+    def git_cmd(cmd, working_dir, log)
+        build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}"
+               ret = Utils.execute_shell_with_log(build_command,log)
+               
+               return ret
+       end
+
+
+    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/JobClean.rb b/src/build_server/JobClean.rb
new file mode 100644 (file)
index 0000000..64265d7
--- /dev/null
@@ -0,0 +1,192 @@
+=begin
+ JobClean.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "BuildServer.rb"
+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 {
+                       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
+
+
+       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 {
+                       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
+
+
+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
+
+                       if not clean_list.include? id then
+                               job_path = "#{jobs_path}/#{id}" 
+                               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
index c46db4855c9a919c3b544e9f8abcdb4c3fb2779c..e005207273b1f06456286e4baabdad1dbb93a7f8 100644 (file)
@@ -34,13 +34,67 @@ require "BuildComm.rb"
 
 class JobLog < Log
 
 
 class JobLog < Log
 
-       def initialize(job, path, stream_out)
-               super(path)
+       def initialize(job, stream_out)
+               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")
+               end
                @parent_job=job
                @second_out = stream_out
        end
 
 
                @parent_job=job
                @second_out = stream_out
        end
 
 
+       def set_second_out( out )
+               @second_out = out
+       end
+
+
+       def init
+               # comm-begin    
+               if not @second_out.nil? and not @second_out.closed? then
+                       BuildCommServer.send_begin(@second_out)
+               end
+       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
        protected
 
        # overide
@@ -50,21 +104,17 @@ class JobLog < Log
                                BuildCommServer.send( @second_out, msg )
                        end
                rescue
                                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
        end     
 
-
 end
 end
index 853c74cc45f45c6795fb23cecfd93f7a4b14b957..e876dc1807c65018c9df26e9a73615b7bd1814a4 100644 (file)
@@ -27,46 +27,73 @@ Contributors:
 =end
 
 require 'fileutils'
 =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"
 $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 "RegisterPackageJob.rb"
 require "packageServer.rb"
 
 require "packageServer.rb"
 
+
 class JobManager
 class JobManager
-       attr_accessor :max_working_jobs, :jobs
+       attr_accessor :max_working_jobs, :jobs, :internal_jobs, :reverse_build_jobs
+       attr_accessor :internal_job_schedule
 
        # initialize
        def initialize( parent )
                @parent = parent
                @jobs = []
 
        # initialize
        def initialize( parent )
                @parent = parent
                @jobs = []
+               @internal_jobs = []
+               @reverse_build_jobs = []
                @max_working_jobs=2
                @new_job_index = 0
                @max_working_jobs=2
                @new_job_index = 0
+               @internal_job_schedule = Mutex.new
+               @latest_job_touch = Mutex.new
+       end
+
+
+       # initialize
+       def init()
+               # load latest job idx if exist
+               file_path = "#{BuildServer::CONFIG_ROOT}/#{@parent.id}/latest_job"
+               if File.exist? file_path then
+                       latest_idx = -1
+                       File.open( file_path, "r" ) { |f|
+                               f.each_line { |l|
+                                       latest_idx = l.strip.to_i
+                                       break
+                               }
+                       }
+                       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
        end
 
 
        # get new id
        def get_new_job_id
-               # check file
-               server_dir = "#{BuildServer::CONFIG_ROOT}/#{@parent.id}"
-               if File.exist? "#{server_dir}/latest_job" then
-                       f = File.open( "#{server_dir}/latest_job", "r" )
-                       @new_job_index = f.gets.strip.to_i + 1
-                       f.close 
-               end     
-
-               # get new id
-               new_id = @new_job_index
-
-               # save it
-               f = File.open( "#{server_dir}/latest_job", "w" )
-               f.puts "#{new_id}"
-               f.close
-
-               return new_id
+               new_idx = 0
+               @latest_job_touch.synchronize {
+                       new_idx = @new_job_index
+
+                       file_path = "#{BuildServer::CONFIG_ROOT}/#{@parent.id}/latest_job"
+                       File.open( file_path, "w" ) { |f|
+                               f.puts "#{@new_job_index}"
+                       }
+
+                       @new_job_index += 1
+               }
+
+               return new_idx
        end
 
        end
 
+       
+       def create_new_register_job( file_path )
+               return RegisterPackageJob.new( file_path, nil, @parent )
+       end
 
        # add a normal job
        def add_job ( new_job )
 
        # add a normal job
        def add_job ( new_job )
@@ -75,31 +102,51 @@ class JobManager
                @jobs.push( new_job )
        end
 
                @jobs.push( new_job )
        end
 
+       # add internal job for multi-build job
+       def add_internal_job( new_job )
+               @parent.log.info "Added new job \"#{new_job.id}\""
+               @internal_jobs.push( new_job )
+       end
+
+       # add reverse build chek job
+       def add_reverse_build_job( new_job )
+               @parent.log.info "Added new job \"#{new_job.id}\""
+               @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"
                Thread.new {
 
        # intialize normal job
        def initialize_job ( job )
                job.status = "INITIALIZING"
                Thread.new {
-                       # pre-verifiy
-                       if not job.pre_verify or job.status == "ERROR" then
-                               job.status = "ERROR"
-                               @parent.log.info "Adding the job \"#{job.id}\" is canceled"
-                               job.terminate()
-                               Thread.current.exit
-                       end
-
-                       # check availabiltiy
-                       if not @parent.check_job_availability( job ) then
-                               job.log.error( "No servers that are able to build your packages.", Log::LV_USER)
-                               job.status = "ERROR"
-                               @parent.log.info "Adding the job \"#{job.id}\" is canceled"
-                               job.terminate()
-                               Thread.current.exit
+                       begin
+                               # init
+                               if not job.init or job.status == "ERROR" then
+                                       if job.cancel_state == "NONE" then job.status = "ERROR" end
+                                       @parent.log.info "Adding the job \"#{job.id}\" is canceled"
+                                       job.terminate()
+                                       Thread.current.exit
+                               end
+                               if job.status != "FINISHED" then
+                                       job.status = "WAITING"
+                               end
+                               @parent.log.info "Checking the job \"#{job.id}\" was finished!"
+                       rescue => e
+                               @parent.log.error e.message
+                               @parent.log.error e.backtrace.inspect
                        end
                        end
-
-                       job.status = "WAITING"
-                       @parent.log.info "Checking the job \"#{job.id}\" was finished!"
                }
                }
+               @parent.log.info "Job \"#{job.id}\" entered INITIALIZING status" 
        end
 
 
        end
 
 
@@ -117,7 +164,8 @@ class JobManager
        def execute_remote(job, rserver)
 
                # start build
        def execute_remote(job, rserver)
 
                # start build
-               if job.execute_remote( rserver) then
+               job.set_remote_job(rserver)
+               if job.execute() then
                        # status change & job control
                        job.status = "REMOTE_WORKING"
                        @parent.log.info "Moved the job \"#{job.id}\" to remote job list" 
                        # status change & job control
                        job.status = "REMOTE_WORKING"
                        @parent.log.info "Moved the job \"#{job.id}\" to remote job list" 
@@ -126,35 +174,119 @@ class JobManager
                end
        end
 
                end
        end
 
+       def cancel_job( job)
+               job.cancel_state = "WORKING"
+               @parent.log.info "Creating thread for canceling the job \"#{job.id}\"" 
+               Thread.new {
+                       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"
+
+                               # call terminate process for job
+                               job.terminate
+                       rescue => e
+                               @parent.log.error e.message
+                               @parent.log.error e.backtrace.inspect
+                       end
+               }
+       end
 
        # handle
        def handle()
 
        # 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"
+                               @parent.log.info "Job \"#{job.id}\" is stopped by ERROR" 
+                               @reverse_build_jobs.delete job  
+                       elsif job.status == "FINISHED" 
+                               @parent.log.info "Job \"#{job.id}\" is removed by FINISH status" 
+                               @reverse_build_jobs.delete job
+                       elsif job.status == "CANCELED" 
+                               @parent.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"
+                               @parent.log.info "Job \"#{job.id}\" is stopped by ERROR" 
+                               @internal_jobs.delete job       
+                       elsif job.status == "FINISHED" 
+                               @parent.log.info "Job \"#{job.id}\" is removed by FINISH status" 
+                               @internal_jobs.delete job
+                       elsif job.status == "CANCELED" 
+                               @parent.log.info "Job \"#{job.id}\" is removed by CANCELED status" 
+                               @internal_jobs.delete job
+                       end
 
 
-               # if "ERROR", "FINISHED", remove it from list
-               for job in @jobs
+                       # 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"
                                @parent.log.info "Job \"#{job.id}\" is stopped by ERROR" 
                                @jobs.delete job        
                        elsif job.status == "FINISHED" 
                        if job.status == "ERROR"
                                @parent.log.info "Job \"#{job.id}\" is stopped by ERROR" 
                                @jobs.delete job        
                        elsif job.status == "FINISHED" 
+                               @parent.log.info "Job \"#{job.id}\" is removed by FINISH status" 
+                               @jobs.delete job
+                       elsif job.status == "CANCELED" 
+                               @parent.log.info "Job \"#{job.id}\" is removed by CANCELED status" 
                                @jobs.delete job
                        end
                                @jobs.delete job
                        end
-               end
 
 
-               # if "JUST_CREATED", initialize it
-               for job in @jobs
-                       if job.status != "JUST_CREATED" then next end
-                       initialize_job( job )
+                       # 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"
+                               @jobs.delete( job )
+                               @parent.log.info "Job \"#{job.id}\" is disconnected by user. Removed!"
+                       end
                end
 
                end
 
-               # get available job
+               # 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 = @parent.get_available_server( job )
                job = get_available_job
 
                # available job not exist?, continue
                if not job.nil? then
                        # oherwise, check remote server
                        rserver = @parent.get_available_server( job )
-
-                       # request for build
                        if rserver != nil and rserver == @parent then
                                execute(job)    
                        elsif rserver != nil  then
                        if rserver != nil and rserver == @parent then
                                execute(job)    
                        elsif rserver != nil  then
@@ -164,92 +296,70 @@ class JobManager
                        end
                end
 
                        end
                end
 
-               # check the connection if job is not asynchronous job
-               for job in @jobs
-                       if ( job.status == "WAITING" or job.status == "REMOTE_WORKING") and 
-                               not job.is_asynchronous_job? and 
-                               not job.is_connected? then
-
-                               @jobs.delete( job )
-                               @parent.log.info "Job \"#{job.id}\" is disconnected by user. Removed!"
-                       end
-               end
        end
 
 
        end
 
 
-       # select the job whith no build-dependency problem 
+       # select the job whith no build-dependency problem
        def get_available_job
        def get_available_job
-       
-               # gather all working jobs
-               all_working_jobs = []
-               for job in @jobs
-                       if job.status == "WORKING" or job.status == "REMOTE_WORKING" then
-                               all_working_jobs.push 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
                        end
                end
-       
-               # for waiting jobs      
-               for job in @jobs
-                       if job.status != "WAITING" then next end
-
-                       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_build_dependency?( wjob ) then
-
-                                       # if there are some changes, check it
-                                       blocked_by.push wjob
-                                       if not job.blocked_by.include? wjob then is_changed = true 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 {
+                       # internal job first
+                       ret = nil
+                       if @internal_jobs.count > 0 then
+                               ret = get_available_job_in_list(@internal_jobs, true)
                        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( " * #{bjob.id} #{bjob.pkginfo.packages[0].source}", Log::LV_USER)
-                                       end
-                                       job.blocked_by = blocked_by
-                               end
+                       # not found, select normal job
+                       if ret.nil? then
+                               ret = get_available_job_in_list(@jobs, false)
                        end
                        end
-               end
-               
-               return nil      
+
+                       return ret
+               }
        end
 
 
        # return "max_working_jobs_cnt - current_working_jobs_cnt"
        def get_number_of_empty_room
                working_cnt = 0
        end
 
 
        # return "max_working_jobs_cnt - current_working_jobs_cnt"
        def get_number_of_empty_room
                working_cnt = 0
-               for job in @jobs
+               parent_list = []
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
                        if job.status == "WORKING" then
                                working_cnt = working_cnt + 1
                        end     
                        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
 
                end
 
-               return @max_working_jobs - working_cnt
+               parent_list.uniq!
+               
+               return @max_working_jobs - working_cnt + parent_list.count
        end
 
 
        # check there are working jobs
        def has_working_jobs
        end
 
 
        # check there are working jobs
        def has_working_jobs
-               working_cnt = 0
-               for job in @jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
                        if job.status == "WORKING" then
                                return true
                        if job.status == "WORKING" then
                                return true
-                       end     
+                       end
                end
 
                return false
                end
 
                return false
@@ -258,11 +368,10 @@ class JobManager
 
        # check there are waiting jobs
        def has_waiting_jobs
 
        # check there are waiting jobs
        def has_waiting_jobs
-               waiting_cnt = 0
-               for job in @jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
                        if job.status == "WAITING" then
                                return true
                        if job.status == "WAITING" then
                                return true
-                       end     
+                       end
                end
 
                return false
                end
 
                return false
@@ -271,44 +380,124 @@ class JobManager
 
        def get_working_jobs
                result = []
 
        def get_working_jobs
                result = []
-               for job in @jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
                        if job.status == "WORKING" then
                                result.push job
                        end     
                end
                        if job.status == "WORKING" then
                                result.push job
                        end     
                end
+
                return result   
        end
 
 
        def get_waiting_jobs
                result = []
                return result   
        end
 
 
        def get_waiting_jobs
                result = []
-               for job in @jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
                        if job.status == "WAITING" then
                                result.push job
                        end     
                end
                        if job.status == "WAITING" then
                                result.push job
                        end     
                end
+
                return result   
        end
 
 
        def get_remote_jobs
                result = []
                return result   
        end
 
 
        def get_remote_jobs
                result = []
-               for job in @jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
                        if job.status == "REMOTE_WORKING" then
                                result.push job
                        end     
                end
                        if job.status == "REMOTE_WORKING" then
                                result.push job
                        end     
                end
+
                return result   
        end
 
 
        def get_pending_jobs
                result = []
                return result   
        end
 
 
        def get_pending_jobs
                result = []
-               for job in @jobs
+               @jobs.each do |job|
                        if job.status == "PENDING" then
                                result.push job
                        end     
                end
                return result   
        end
                        if job.status == "PENDING" then
                                result.push job
                        end     
                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
+
+               # for waiting 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
+                               return job
+                       end
+               end
+
+               return nil
+       end
+
 end
 end
diff --git a/src/build_server/LocalBuildJob.rb b/src/build_server/LocalBuildJob.rb
deleted file mode 100644 (file)
index e178616..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-=begin
- LocalBuildJob.rb
-
-Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
-
-Contact:
-Taejun Ha <taejun.ha@samsung.com>
-Jiil Hyoun <jiil.hyoun@samsung.com>
-Donghyuk Yang <donghyuk.yang@samsung.com>
-DongHee Yang <donghee.yang@samsung.com>
-
-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"
-require "BuildJob.rb"
-require "utils.rb"
-
-class LocalBuildJob < BuildJob
-       attr_accessor :id, :status, :pkginfo, :pkgsvr_client, :thread, :log, :rev_fail_list, :rev_success_list, :source_path
-
-       # initialize
-       def initialize (local_path, os, pkgserver_url, options, server, parent, outstream, resolve )
-               super()
-        @rev_fail_list = []
-        @rev_success_list = []
-               @id = server.jobmgr.get_new_job_id()
-               @server = server
-               @parent = parent
-               @local_path = local_path
-               @os = os
-               @host_os = Utils::HOST_OS
-               if not pkgserver_url.nil? 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 = @local_path
-        @pkginfo = nil
-        @pkgsvr_client = 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 )
-       end
-
-
-       def terminate()
-
-               # report error
-               if @status == "ERROR" then
-                       @log.error( "Job is stopped by ERROR", Log::LV_USER)
-               else
-                       # if succeeded, clean up
-                       FileUtils.rm_rf "#{@job_working_dir}"
-               end
-
-               # 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 "%-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 )  
-                               contents.push("%-30s| %10s | %10s" % [ pkg.package_name, pkg.version, pkg.os] )
-                       end
-                       
-                       if @status == "ERROR" then 
-                               subject = "[DIBS] Build fail" 
-                               contents.push " "
-                               contents.push "check log file"
-                               contents.push "* Log : #{@server.job_log_url}/#{@id}/log"
-                       else
-                               subject = "[DIBS] Build success" 
-                       end
-                       Mail.send_mail(mail_list, subject, contents.join("\n")) 
-               end
-                       
-               # close logger
-               @log.close
-
-               # 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 )
-               end
-       end
-
-
-       # verify
-       def pre_verify
-               @log.info( "Verifying job input...", Log::LV_USER)
-
-               # check pkginfo.manifest
-               if not File.exist? "#{@source_path}/package/pkginfo.manifest"
-                       @log.error( "#{@source_path}/package/pkginfo.manifest doest not exist", Log::LV_USER)
-                       @status = "ERROR"
-                       return false
-               end
-
-               # set pkginfo
-               @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
-
-               return true
-       end
-
-end
diff --git a/src/build_server/MultiBuildJob.rb b/src/build_server/MultiBuildJob.rb
new file mode 100644 (file)
index 0000000..9e28c9e
--- /dev/null
@@ -0,0 +1,489 @@
+=begin
+
+ MultiBuildJob.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "BuildServer.rb"
+require "JobLog.rb"
+require "mail.rb"
+
+class MultiBuildJob
+
+       attr_accessor :id, :server, :pre_jobs, :os, :type
+       attr_accessor :status, :log, :source_path, :cancel_state
+       attr_accessor :pkgsvr_client, :thread, :sub_jobs
+
+       # initialize
+       def initialize (server)
+               @server = server
+               @id = server.jobmgr.get_new_job_id()
+               @log = nil
+               @type = "MULTIBUILD"
+               @os = "Unknown"
+
+               @status = "JUST_CREATED"
+               @host_os = Utils::HOST_OS
+               @pkgserver_url = @server.pkgserver_url
+               @job_root = "#{@server.path}/jobs/#{@id}"
+               @source_path = @job_root+"/temp"
+               @job_working_dir=@job_root+"/works"
+               @buildroot_dir = "#{@job_root}/buildroot"
+               @pre_jobs = [] #pre-requisite jobs
+               @cancel_state = "NONE"
+
+               # children
+               @sub_jobs = []
+       end
+
+
+       def get_buildroot()
+               return @buildroot_dir
+       end
+
+
+       def get_parent_job()
+               return nil
+       end
+
+
+       def is_rev_build_check_job()
+               return false
+       end
+
+       # execute
+       def execute(sync=false)
+               @log.info( "Invoking a thread for MULTI-BUILD Job #{@id}", Log::LV_USER)
+               if @status == "ERROR" then return  end
+               @thread = Thread.new {
+                       begin
+                               # main
+                               thread_main()
+                       
+                               # close 
+                               terminate()
+                       rescue => e
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                       end     
+               }
+
+               if sync then
+                       @thread.join
+               end
+               
+               return true      
+       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
+               @pkgsvr_client =  Client.new(@pkgserver_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
+
+
+       def is_sub_job?
+               return false
+       end
+
+
+       def get_sub_jobs()
+               return @sub_jobs
+       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 )
+
+               # 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 )
+               # 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 )
+
+               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
+
+       # set logger 
+       def set_logger( logger )
+               @log =  logger
+       end
+
+
+       # add sub job
+       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
+
+
+       def progress
+               # do noting
+               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
+       #
+       protected
+
+
+       # main module   
+       def thread_main
+               @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 {
+                       @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
+               }
+
+               # 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
+
+
+       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( @server.pkgserver_url, nil, @log )
+               snapshot = u_client.upload( @server.pkgserver_addr, @server.pkgserver_port, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd, binpkg_path_list)
+
+               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 (file)
index 0000000..f395856
--- /dev/null
@@ -0,0 +1,187 @@
+=begin
+ PackageSync.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "BuildServer.rb"
+require "Action.rb"
+require "ScheduledActionHandler.rb"
+
+
+class PackageSyncAction < Action
+       @@new_id = 0
+       
+       def initialize( time, url, proxy, server )
+               super(time, server.pkg_sync_period)
+               my_id = @@new_id
+               @@new_id += 1
+               @pkgsvr_url = url
+               @proxy = proxy
+               @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 
+               else
+                       FileUtils.mkdir_p @download_path
+                       FileUtils.mkdir_p @original_path
+               end
+
+               # create client
+               @pkgsvr_client = Client.new( @pkgsvr_url, @download_path, @server.log )
+               @main_client = Client.new( @server.pkgserver_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
+
+               # if updates are found, download them
+               downloaded_files = []
+               pkgs.each { |pkg|
+                       pkg_name=pkg[0]; os=pkg[1]
+
+                       files = @pkgsvr_client.download(pkg_name, os, false)
+                       downloaded_files += files
+               }
+
+               # request to register
+               registered_jobs = []
+               downloaded_files.each { |file_path|
+                       @server.log.info "Creating new job for registering \"#{file_path}\""
+                       new_job = @server.jobmgr.create_new_register_job( file_path )
+                       logger = JobLog.new( new_job, nil )
+                       new_job.set_logger(logger)
+                       logger.init
+
+                       # add
+                       @server.jobmgr.add_job( new_job )
+                       registered_jobs.push new_job
+               }
+
+               # wait for finish all jobs
+               all_jobs_finished = false
+        while not all_jobs_finished
+                       unfinished_jobs = registered_jobs.select { |j| 
+                               (j.status != "ERROR" and j.status != "FINISHED" and j.status != "CANCELED")
+                       }
+                       if unfinished_jobs.empty? then 
+                               all_jobs_finished = true 
+                       else
+                               sleep 10
+                       end
+               end
+       
+               # remove files  
+               downloaded_files.each { |file_path|
+                       @server.log.info "Removed downloaded file: \"#{file_path}\""
+                       FileUtils.rm_rf file_path
+               }
+       end     
+
+
+       protected
+       def check_package_update
+               pkgs = []
+
+               # update
+               @pkgsvr_client.update()
+               @main_client.update()
+
+               # for all BINARY project
+               bin_prjs = @server.prjmgr.projects.select { |p| (p.type == "BINARY") }
+               bin_prjs.each { |p|
+                       pkg_name = p.pkg_name
+                       p.os_list.each { |os|
+                               # get pkg version in server
+                               main_ver = @main_client.get_attr_from_pkg(pkg_name, os, "version")
+                               if main_ver.nil? then next end
+                               remote_ver = @pkgsvr_client.get_attr_from_pkg(pkg_name, os, "version")
+                               if remote_ver.nil? then next end
+       
+                               if Version.new(main_ver) < Version.new(remote_ver) then
+                                       pkgs.push [pkg_name, os]
+                               end
+                       }
+               }
+
+               return pkgs
+       end
+
+end
+
+
+class PackageServerSynchronizer
+       attr_accessor :quit
+
+       # init
+       def initialize( server )
+               @server = server
+               @handler = ScheduledActionHandler.new
+       end
+
+
+       # start thread
+       def start()
+
+               time = Time.new + 60
+               @server.remote_pkg_servers.each { |entry|
+                       url=entry[0]; proxy=entry[1]
+                       @handler.register( PackageSyncAction.new(time, url, proxy, @server) )
+                       @server.log.info "Registered package-sync action for server \"#{url}\""
+               }
+
+               # start handler
+               @handler.start 
+       end
+end
diff --git a/src/build_server/ProjectManager.rb b/src/build_server/ProjectManager.rb
new file mode 100644 (file)
index 0000000..9d61df1
--- /dev/null
@@ -0,0 +1,352 @@
+=begin
+ ProjectManager.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "GitBuildProject.rb"
+require "BinaryUploadProject.rb"
+require "MultiBuildJob.rb"
+require "PackageManifest.rb"
+require "package.rb"
+
+class ProjectManager
+       attr_accessor :projects
+
+       # initialize
+       def initialize( server )
+               @server = server
+               @projects = []
+               @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
+
+               # scan all projects 
+               Dir.new(@project_root).entries.each do |name|
+                       # skip . or ..
+                       if name.eql? "." or name.eql? ".." then next end
+                               
+                       # create project
+                       @server.log.info "Loading project : #{name}"
+                       prj = load_project( name )
+                       if not prj.nil? then 
+                               @projects.push prj
+                       end
+               end
+
+       end
+
+
+       # get_project of the name
+       def get_project ( name )
+               @projects.each do |prj|
+                       if prj.name.eql? name then return prj end
+               end
+       
+               return nil
+       end
+
+
+       def add_git_project(name , repos, branch, passwd, os_list)
+               prj = get_project( name)
+               if not prj.nil? then return false end
+               
+               new_prj = GitBuildProject.new(name, repos, branch, @server, os_list)
+               if not passwd.nil? and not passwd.empty? then
+                       new_prj.passwd = passwd
+               end
+               @projects.push new_prj
+
+               # check project directory
+               if not File.exist? "#{@project_root}/#{name}" then
+                       FileUtils.mkdir_p "#{@project_root}/#{name}"
+               end
+
+               # write configuration
+               write_configuration(name, repos, branch, passwd, os_list)
+
+               return true
+       end
+
+
+       def add_binary_project(name, pkg_name, passwd, os_list)
+               prj = get_project( name)
+               if not prj.nil? then return false end
+               
+               new_prj = BinaryUploadProject.new(name, pkg_name, @server, os_list)
+               if not passwd.nil? and not passwd.empty? then
+                       new_prj.passwd = passwd
+               end
+               @projects.push new_prj
+
+               # check project directory
+               if not File.exist? "#{@project_root}/#{name}" then
+                       FileUtils.mkdir_p "#{@project_root}/#{name}"
+               end
+
+               # write configuration
+               write_configuration_for_binary_project(name, pkg_name, passwd, os_list)
+
+               return true
+       end
+
+
+       def add_remote_project( name, server_id)
+       end
+
+
+       # create new job for project
+       # if cannot create, return nil
+       def create_new_job( name, os )
+               prj = get_project( name )
+               if prj.nil? then return nil 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( )
+               # create multi job
+               result = MultiBuildJob.new( @server )
+
+               # create sub jobs
+               @projects.each do |prj|
+                       if prj.type != "GIT" 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 )
+                               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)
+               result = []
+               @projects.each do |prj|
+                       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)
+               @projects.each do |prj|
+                       # check project provide target package  
+                       if prj.include_package?(pkg_name) then
+                               return prj
+                       end
+               end
+
+               return nil
+       end
+
+
+       # get project from git repository
+       def get_git_project( repos )
+               @projects.each { |prj|
+                       if prj.type == "GIT" and prj.repository == repos then 
+                               return prj 
+                       end
+               }
+       
+               return nil
+       end
+
+
+       def create_unnamed_git_project(repos)
+               name = "UNNAMED_PRJ_#{@projects.count}"
+               branch = "master"
+               passwd = nil
+               os_list = Utils.get_all_OSs()
+               # add
+               add_git_project(name , repos, branch, passwd, os_list)
+               # get
+               return get_project(name)        
+       end
+
+       protected
+
+       # load and create project       
+       def load_project(name)
+       
+               # check config file 
+               config_file = "#{@project_root}/#{name}/build"
+               if not File.exist? config_file then return nil end
+
+               # read configuration
+               type="GIT"
+               passwd=""
+               repos="none"
+               branch="master"
+               os_list = @server.supported_os_list
+               rserver_id=nil
+               pkg_name=nil
+               File.open( config_file, "r" ) do |f|
+                       f.each_line do |l| 
+                               idx = l.index("=") + 1
+                               length = l.length - idx 
+
+                               if l.start_with?("TYPE=")
+                                       type = l[idx,length].strip
+                               elsif l.start_with?("PASSWD=")
+                                       passwd = l[idx,length].strip
+                               elsif l.start_with?("GIT_REPOSITORY=")
+                                       repos = l[idx,length].strip
+                               elsif l.start_with?("GIT_BRANCH=")
+                                       branch = l[idx,length].strip
+                               elsif l.start_with?("OS_LIST=")
+                                       os_list = l[idx,length].strip.split(",")
+                               elsif l.start_with?("REMOTE_SERVER_ID=")
+                                       rserver_id = l[idx,length].strip
+                               elsif l.start_with?("PACKAGE_NAME=")
+                                       pkg_name = l[idx,length].strip
+                               else
+                                       next    
+                               end 
+                       end
+               end
+
+               # write back & create project
+               if type == "GIT" then   
+                       write_configuration(name, repos, branch, passwd, os_list)
+                       new_project = GitBuildProject.new(name, repos, branch, @server, os_list)
+
+                       # read source info
+                       sources_file = "#{@project_root}/#{name}/sources"
+                       if File.exist? sources_file then
+                               File.open(sources_file, "r") do |f|
+                                       f.each_line do |l|
+                                               version = l.split(",")[0].strip
+                                               info = l.split(",")[1].strip
+       
+                                               new_project.add_source_info( version, info )
+                                       end
+                               end             
+                       end
+       
+                       # read pkginfo
+                       pkginfo_dir = "#{@project_root}/#{name}/pkginfos"
+                       if not File.exist? pkginfo_dir then FileUtils.mkdir_p pkginfo_dir end
+                       Dir.new(pkginfo_dir).entries.each do |file|
+                               if file.eql? "." or file.eql? ".." then next end
+                       
+                               vlen = file.length - ".manifest".length 
+                               version = file[0,vlen]
+                               new_project.add_package_info( version, "#{pkginfo_dir}/#{file}" )
+                       end
+
+               elsif type == "BINARY" then
+                       write_configuration_for_binary_project(name, pkg_name, passwd, os_list)
+                       new_project = BinaryUploadProject.new(name, pkg_name, @server, os_list)
+               end
+
+
+               # set passwd if exist
+               if not passwd.empty? then
+                       new_project.passwd = passwd
+               end
+
+               
+               return new_project
+       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
+
+
+end
diff --git a/src/build_server/RegisterPackageJob.rb b/src/build_server/RegisterPackageJob.rb
new file mode 100644 (file)
index 0000000..0655ef0
--- /dev/null
@@ -0,0 +1,544 @@
+=begin
+
+ RegisterBinaryJob.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "BuildServer.rb"
+require "JobLog.rb"
+require "mail.rb"
+require "utils.rb"
+require "ReverseBuildChecker.rb"
+
+class RegisterPackageJob
+
+       attr_accessor :id, :server, :pre_jobs, :os, :type
+       attr_accessor :status, :log, :source_path
+       attr_accessor :pkgsvr_client, :thread, :pkg_type
+       attr_accessor :pkg_name, :pkginfo, :cancel_state
+       
+
+       # initialize
+       def initialize( local_path, project, server, ftpurl=nil )
+               @server = server
+               @id = server.jobmgr.get_new_job_id()
+               @log = nil
+               @type = "REGISTER"
+
+               @status = "JUST_CREATED"
+               @host_os = Utils::HOST_OS
+               @pkgserver_url = @server.pkgserver_url
+               @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"
+               @pre_jobs = []
+
+               @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
+       end
+
+
+       def is_sub_job?
+               return false
+       end
+
+
+       def get_project()
+               return @project
+       end
+
+
+       def get_buildroot()
+               return @buildroot_dir
+       end
+
+       def get_parent_job()
+               return nil
+       end
+
+
+       def is_rev_build_check_job()
+               return false
+       end
+
+       # execute
+       def execute(sync=false)
+               @log.info( "Invoking a thread for REGISTER Job #{@id}", Log::LV_USER)
+               if @status == "ERROR" then return  end
+               @thread = Thread.new {
+                       begin
+                               thread_main()
+                               terminate()
+                       rescue => e
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                       end
+               }
+
+               if sync then
+                       @thread.join
+               end
+               
+               return 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 not @project.nil? 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(@pkgserver_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 @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
+                       # clean up
+                       @server.cleaner.clean(@id)
+                       if not @project.nil? then
+                               @project.set_log_cnt( @log.cnt )
+                               @project.write_ext_info
+                       end
+               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 )
+               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 )
+               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
+
+       # set logger 
+       def set_logger( logger )
+               @log =  logger
+       end
+
+
+       def progress
+               if not @log.nil? then
+                       if @project.nil? or @project.get_latest_log_cnt.nil? then
+                               return "--% (#{log.cnt.to_s} lines) "
+                       else
+                               return ( ( @log.cnt * 100 ) / @project.get_latest_log_cnt ).to_s + "%"
+                       end
+               end
+               # if log is nil then can't figure progress out
+               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
+       #
+       protected
+
+
+       # main module   
+       def thread_main
+               @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 ReverseBuildChecker.check( self, true, os ) then
+                                       @status = "ERROR"
+                                       @log.error( "Reverse-build-check failed!" )
+                                       return
+                               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)
+
+               # 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( @server.pkgserver_url, nil, @log )
+               snapshot = u_client.upload( @server.pkgserver_addr, @server.pkgserver_port, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd, binpkg_path_list)
+
+               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
index 8e9355b8b84634bacfae6ab6f7b0dff4f3e536f2..845a0c87cf89eb59760c81ebdc41fe560689f9b9 100644 (file)
@@ -1,5 +1,5 @@
 =begin
 =begin
+
  RemoteBuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
  RemoteBuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -35,10 +35,9 @@ class RemoteBuildJob < BuildJob
        attr_accessor :id
 
        # initialize
        attr_accessor :id
 
        # initialize
-       def initialize (id)
-               super()
+       def initialize (id,server)
+               super(id,nil,nil,server)
                @id = id
                @type = nil
                @id = id
                @type = nil
-               @outstream = nil
        end
 end
        end
 end
index 07f4fa5947f0b0dc7f16fc0f4aaace85764d66f9..8c71460220187e8bfb64b4ce3cc4c65707e3a681 100644 (file)
@@ -30,13 +30,15 @@ require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)
 require "RemoteBuildJob.rb"
 require "BuildComm.rb"
 $LOAD_PATH.unshift File.dirname(__FILE__)
 require "RemoteBuildJob.rb"
 require "BuildComm.rb"
+require 'thread'
 
 class RemoteBuildServer
        attr_accessor :ip, :port, :status, :host_os
        attr_accessor :max_working_jobs, :working_jobs, :waiting_jobs
 
 class RemoteBuildServer
        attr_accessor :ip, :port, :status, :host_os
        attr_accessor :max_working_jobs, :working_jobs, :waiting_jobs
+       attr_accessor :pkgserver_url, :path
 
        # initialize
 
        # initialize
-       def initialize(ip, port)
+       def initialize(ip, port, parent)
                @ip = ip
                @port = port
                @status = "DISCONNECTED"
                @ip = ip
                @port = port
                @status = "DISCONNECTED"
@@ -44,6 +46,10 @@ class RemoteBuildServer
                @max_working_jobs = 2
                @working_jobs = []
                @waiting_jobs = []
                @max_working_jobs = 2
                @working_jobs = []
                @waiting_jobs = []
+               @pkgserver_url = parent.pkgserver_url
+               @path = ""
+               @file_transfer_cnt_mutex = Mutex.new
+               @file_transfer_cnt = 0
        end
 
 
        end
 
 
@@ -63,10 +69,10 @@ class RemoteBuildServer
        def update_state
 
                # send 
        def update_state
 
                # send 
-               @status = "DISCONNECTED"
+               #@status = "DISCONNECTED"
                client = BuildCommClient.create( @ip, @port )
                if client.nil? then return end
                client = BuildCommClient.create( @ip, @port )
                if client.nil? then return end
-               if client.send("QUERY,SYSTEM") then
+               if client.send("QUERY|SYSTEM") then
                        result = client.read_lines do |l|
                                tok = l.split(",").map { |x| x.strip }
                                @host_os = tok[0]
                        result = client.read_lines do |l|
                                tok = l.split(",").map { |x| x.strip }
                                @host_os = tok[0]
@@ -83,15 +89,15 @@ class RemoteBuildServer
                @waiting_jobs = []
                client = BuildCommClient.create( @ip, @port )
                if client.nil? then return end
                @waiting_jobs = []
                client = BuildCommClient.create( @ip, @port )
                if client.nil? then return end
-               if client.send("QUERY,JOB") then
+               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]
                        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)
+                               new_job = RemoteBuildJob.new(job_id,self)
                                case job_status
                                case job_status
-                               when "WAITING" 
+                               when "WAITING", "JUST_CREATED", "INITIALIZING"
                                        @waiting_jobs.push new_job
                                when "WORKING" 
                                        @working_jobs.push new_job
                                        @waiting_jobs.push new_job
                                when "WORKING" 
                                        @working_jobs.push new_job
@@ -123,5 +129,22 @@ class RemoteBuildServer
        def has_waiting_jobs
                return (@waiting_jobs.count > 0)
        end
        def has_waiting_jobs
                return (@waiting_jobs.count > 0)
        end
+
+
+       def add_file_transfer()
+               @file_transfer_cnt_mutex.synchronize {
+                       @file_transfer_cnt += 1
+               }
+       end
+
+       def remove_file_transfer()
+               @file_transfer_cnt_mutex.synchronize {
+                       @file_transfer_cnt -= 1
+               }
+       end
+
+       def get_file_transfer_cnt()
+               return @file_transfer_cnt
+       end
 end
 
 end
 
diff --git a/src/build_server/RemoteBuilder.rb b/src/build_server/RemoteBuilder.rb
new file mode 100644 (file)
index 0000000..0a1ea23
--- /dev/null
@@ -0,0 +1,210 @@
+=begin
+ RemoteBuilder.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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"
+
+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 = Log.new(nil)
+       end
+
+       
+       # build
+       def build( git_repos, source_path, os, is_rev_build, srcinfo, no_reverse, local_pkgs )
+               @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)
+
+        @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
+                       result=client.send_file( @ftp_addr, @ftp_port, @ftp_username, @ftp_passwd, file_path )
+                       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 = "0")
+               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
+               # format: BUILD|GIT|repository|passwd|os|async|no_reverse|internal|rev-build|commit|pkgs|dock_num
+               # value : BUILD|GIT|repository|      |os|NO   |no_reverse|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}|YES|#{rev}|#{commit}|#{pkg_list}|#{dock}"
+        if client.send( msg ) then 
+            result = client.read_lines do |l|
+                # write log first
+                @log.output( l.strip, Log::LV_USER)
+                               # check build result
+                if l.include? "Job is stopped by ERROR" or
+                                       l.include? "Error:" then                                           
+                    result = false
+                                       break
+                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
+        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
+                       result=client.receive_file( @ftp_addr, @ftp_port, @ftp_username, @ftp_passwd, file_path )
+                       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 (file)
index 0000000..7ae943e
--- /dev/null
@@ -0,0 +1,218 @@
+=begin
+ ReverseBuildChecker.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "BuildServer.rb"
+require "JobLog.rb"
+require "PackageManifest.rb"
+require "BuildJob.rb"
+require "RegisterPackageJob.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)
+
+               # 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 { |fp|
+                                       f_prj = fp[0]
+                                       f_os =  fp[1]
+                                       if rev_prj == f_prj and rev_os == f_os then     
+                                               found = true
+                                               break
+                                       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 )
+
+                       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
index f7656a539e5b80c8293326aa86d4b8a852f5d24c..ae438a98798a844bc7e881c83f0263668c00cc1d 100644 (file)
@@ -27,8 +27,6 @@ Contributors:
 =end
 
 $LOAD_PATH.unshift File.dirname(__FILE__)
 =end
 
 $LOAD_PATH.unshift File.dirname(__FILE__)
-require "GitBuildJob.rb"
-require "LocalBuildJob.rb"
 require "JobLog.rb"
 require "BuildComm.rb"
 
 require "JobLog.rb"
 require "BuildComm.rb"
 
@@ -40,13 +38,22 @@ class SocketJobRequestListener
                @parent_server = parent
                @thread = nil
                @finish_loop = false
                @parent_server = parent
                @thread = nil
                @finish_loop = false
+               @comm_server = nil
                @log = @parent_server.log
        end
 
        # start listening
        def start()
                @thread = Thread.new {
                @log = @parent_server.log
        end
 
        # start listening
        def start()
                @thread = Thread.new {
-                       main()          
+                       # 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
 
@@ -63,21 +70,26 @@ class SocketJobRequestListener
        def main()
                # server open
                begin
        def main()
                # server open
                begin
-                       server = BuildCommServer.new(@parent_server.port, @log)
+                       ftp_url = Utils.generate_ftp_url(@parent_server.ftp_addr, @parent_server.ftp_port,
+                               @parent_server.ftp_username, @parent_server.ftp_passwd)
+                       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"
                rescue
                        @log.info "Server creation failed"
+                       puts "Server creation failed"
+                       @parent_server.stop
                        return
                end
 
                # loop
                @log.info "Entering Control Listening Loop ... "        
                @finish_loop = false
                        return
                end
 
                # loop
                @log.info "Entering Control Listening Loop ... "        
                @finish_loop = false
-               server.wait_for_connection(@finish_loop) do |req|
+               @comm_server.wait_for_connection(@finish_loop) do |req|
                                handle_job_request( req )
                end     
 
                # quit
                                handle_job_request( req )
                end     
 
                # quit
-               server.terminate
+               @comm_server.terminate
        end
 
 
        end
 
 
@@ -99,8 +111,8 @@ class SocketJobRequestListener
 
                # parse request
                cmd = ""
 
                # 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
                end
                
                case  cmd
@@ -110,8 +122,36 @@ class SocketJobRequestListener
                        handle_cmd_resolve( req_line, req )
                when "QUERY"
                        handle_cmd_query( req_line, req )
                        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 "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 {
+                               begin
+                               handle_cmd_download( req_line, req )
+                               rescue => e
+                                       @log.error "Transfering file failed!"
+                                       @log.error e.message
+                                       @log.error e.backtrace.inspect
+                               end
+            }             
+               when "UPLOAD"
+            Thread.new {
+                               begin
+                               handle_cmd_upload( req_line, req )
+                               rescue => e
+                                       @log.error "Transfering file failed!"
+                                       @log.error e.message
+                                       @log.error e.backtrace.inspect
+                               end
+            }                
                else
                        @log.info "Received Unknown REQ: #{req_line}" 
                        raise "Unknown request: #{req_line}"
                else
                        @log.info "Received Unknown REQ: #{req_line}" 
                        raise "Unknown request: #{req_line}"
@@ -122,87 +162,205 @@ class SocketJobRequestListener
 
        # "BUILD"       
        def handle_cmd_build( line, req )
 
        # "BUILD"       
        def handle_cmd_build( line, req )
-               tok = line.split(",").map { |x| x.strip }
-               if tok.count < 4 then 
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 3 then 
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                end
 
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                end
 
-               case tok[1]
-               # BUILD,GIT,repos,commit,os,url,async
-               when "GIT"
-                       @log.info "Received BUILD GIT => #{tok[2]}"
+               # check type
+               if tok[1] != "GIT" then 
+                       @log.info "Received Wrong REQ: #{line}"
+                       raise "Invalid request format is used: #{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)
+               # Case1. BUILD|GIT|project_name|passwd|os_list|async|no_reverse
+               # Case2. BUILD|GIT|git_repos||os|async|no_reverse|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"
+               is_internal = tok[7].eql? "YES"
+               rev_job = tok[8].eql? "YES"
+               git_commit = (not tok[9].nil? and not tok[9].empty?) ? tok[9] : nil
+               pkg_files = (not tok[10].nil? and not tok[10].empty?) ? tok[10].split(",") : []
+               dock_num = (not tok[11].nil? and not tok[11].empty?) ? tok[11].strip : "0"
+
+               # check supported os if not internal job
+               if not is_internal then
+                       os_list = check_supported_os( os_list , req )
+                       if os_list.nil? or os_list.empty? then
+                               raise "Unsupported OS name is used!"
                        end
                        end
-                       BuildCommServer.send_begin(req)
+               end
 
 
-                       # 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)
+               # multi build job
+               if project_name_list.count > 1 or os_list.count > 1 then
+                       new_job_list = []
+                       i = 0
+                       project_name_list.each { |pname|
+                               if not passwd_list[i].nil? then passwd = passwd_list[i]
+                               else passwd = passwd_list[0] end
+                               check_build_project(pname,passwd,req)   
+                               os_list.each { |os|
+                                       new_job = create_new_job( pname, os )
+                                       if new_job.nil? then
+                                               @log.warn "\"#{pname}\" does not support #{os}"
+                                               next
+                                       end
+                                       new_job_list.push new_job
+                                       @log.info "Received a request for building this project : #{pname}, #{os}"
+                               }
+                               i = i + 1
+                       }
+
+                       if new_job_list.count > 1 then
+                               new_job = @parent_server.prjmgr.create_new_multi_build_job( new_job_list )
+                       elsif new_job_list.count == 1 then
+                               new_job = new_job_list[0]
                        else
                        else
-                               new_job.log.info( "Added new job \"#{new_job.id}\"!", Log::LV_USER)
+                               raise "Multi-Build Job creation failed!"
                        end
 
                        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")
-                               else
-                                       req.puts( "Info: Added new job \"#{new_job.id}\"!")
-                               end
+               # transfered job
+               elsif is_internal then
+                       git_repos = project_name_list[0]
+                       os = os_list[0]
 
 
-                               BuildCommServer.send_end(req)
-                               BuildCommServer.disconnect(req)
-                       end     
+                       new_job = create_new_internal_job(git_repos, os, git_commit, pkg_files, dock_num )
+                       if rev_job then new_job.set_rev_build_check_job(nil) end
 
 
-                       # add
-                       @parent_server.jobmgr.add_job( new_job )
+               # single job
+               elsif project_name_list.count == 1 and os_list.count == 1 then
+                       pname = project_name_list[0]
+                       os = os_list[0]
 
 
-               # BUILD,LOCAL,path,os,url
-               when "LOCAL"
-                       @log.info "Received BUILD LOCAL => #{tok[2]}" 
-                       
-                       BuildCommServer.send_begin(req)
-                       @parent_server.jobmgr.add_job( 
-                               LocalBuildJob.new( tok[2], tok[3], tok[4], [], @parent_server, nil, req, false))
+                       check_build_project(pname,passwd,req)
+                       new_job = create_new_job( pname, os )
                else
                else
-                       @log.info "Received Wrong REQ: #{line}"
-                       raise "Invalid request format is used: #{line}"
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: There is no valid job to build!"
+                       BuildCommServer.send_end(req)
+                       raise "No valid jobs!"
+               end
+
+               if no_reverse then new_job.set_no_reverse end
+
+               # create logger and set
+               logger = JobLog.new( new_job, req )
+               if not async then new_job.set_logger(logger) end
+               logger.init
+       
+               # 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
+
+               # if asynchronouse, quit connection
+               if async then
+                       logger.info( "Above job(s) will be processed asynchronously!", Log::LV_USER)
+                       logger.close
                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
+
+
+       def check_build_project(prj_name, passwd, req)
+               # check project
+               prj = check_project_exist(prj_name, req)
+               if prj.nil? then
+                       raise "Requested project does not exist!"
+               end
+
+               # check passwd
+               if not check_project_password(prj, passwd, req) then
+                       raise "Project's password is not matched!!"
+               end
+
+        # check project type
+        if prj.type == "BINARY" then
+            BuildCommServer.send_begin(req)
+            req.puts "Can't build about Binary type package."
+            BuildCommServer.send_end(req)
+            raise "Can't build about Binary type package."
+        end
        end
 
 
        # "RESOLVE"     
        def handle_cmd_resolve( line ,req)
        end
 
 
        # "RESOLVE"     
        def handle_cmd_resolve( line ,req)
-               tok = line.split(",").map { |x| x.strip }
-               if tok.count < 4 then 
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 3 then 
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                end
 
                case tok[1]
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                end
 
                case tok[1]
-               # RESOLVE,GIT,repos,commit,os,url
+               # RESOLVE|GIT|repos|commit|os|async
                when "GIT"
                when "GIT"
-                       @log.info "Received RESOLVE GIT => #{tok[2]}"
+                       # parse
+                       project_name=tok[2]
+                       passwd=tok[3]
+                       os=tok[4]
+                       async = tok[5].eql? "YES"
+
+                       # check project
+                       prj = check_project_exist(project_name, req)
+                       if prj.nil? then
+                               raise "Requested project does not exist!"
+                       end
+       
+                       # check passwd
+                       if not check_project_password(prj, passwd, req) then
+                               raise "Project's password is not matched!!"
+                       end
 
 
-                       BuildCommServer.send_begin(req)
-                       @parent_server.jobmgr.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]}" 
+                       # check os
+                       os_list = check_supported_os( os , req )
+                       if os_list.nil? or os_list.empty? then
+                               raise "Unsupported OS name is used!"
+                       end
+                       os = os_list[0]
+                       
+                       # create new job
+                       new_job = create_new_job( project_name, os )
+                       if new_job.nil? then
+                               raise "Creating build job failed : #{project_name}, #{os}"
+                       end
+                       @log.info "Received a request for resolving this project : #{project_name}, #{os}"
 
 
-                       BuildCommServer.send_begin(req)
-                       @parent_server.jobmgr.add_job( 
-                               LocalBuildJob.new( tok[2], tok[3], tok[4], [], @parent_server, nil, req, true))
+                       # resolve 
+                       new_job.set_resolve_flag()
+
+                       # create logger and set
+                       logger = JobLog.new( new_job, req )
+                       if not async then new_job.set_logger(logger) end
+                       logger.init
+               
+                       # 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
+
+                       # if asynchronouse, quit connection
+                       if async then
+                               logger.info( "Above job(s) will be processed asynchronously!", Log::LV_USER)
+                               logger.close
+                       end     
+
+                       @parent_server.jobmgr.add_job( new_job ) 
                else
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                else
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
@@ -212,27 +370,58 @@ class SocketJobRequestListener
 
        # "QUERY"
        def handle_cmd_query( line, req )
 
        # "QUERY"
        def handle_cmd_query( line, req )
-               tok = line.split(",").map { |x| x.strip }
+               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}"
                end
        
                case tok[1]
                if tok.count < 2 then 
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                end
        
                case tok[1]
+
+               # QUERY, FTP
+               when "FTP"
+                       BuildCommServer.send_begin(req)
+                       BuildCommServer.send(req,"#{@parent_server.ftp_addr},#{@parent_server.ftp_username},#{@parent_server.ftp_passwd}")
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
                # QUERY,JOB
                when "JOB"
                        #puts "Received QUERY JOB"
 
                # QUERY,JOB
                when "JOB"
                        #puts "Received QUERY JOB"
 
+                       # 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
                        BuildCommServer.send_begin(req)
                        BuildCommServer.send_begin(req)
-                       for job in @parent_server.jobmgr.get_working_jobs
-                               BuildCommServer.send(req,"WORKING,#{job.id},#{job.pkginfo.packages[0].source}")
-                       end
-                       for job in @parent_server.jobmgr.get_waiting_jobs
-                               BuildCommServer.send(req,"WAITING,#{job.id},#{job.pkginfo.packages[0].source}")
-                       end
-                       for job in @parent_server.jobmgr.get_remote_jobs
-                               BuildCommServer.send(req,"REMOTE ,#{job.id},#{job.pkginfo.packages[0].source}")
+                       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}")
+                                       else
+                                               BuildCommServer.send(req,"#{status},#{job.id},#{job.get_project().name},#{job.os} #{job.progress}")
+                                       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}")
+                                       else
+                                               BuildCommServer.send(req,"#{status},#{job.id},#{job.pkg_name}")
+                                       end
+                               when "MULTIBUILD"
+                                       BuildCommServer.send(req,"#{status},#{job.id},MULTI-BUILD : #{job.sub_jobs.map{|x| x.id}.join(" ")}")
+                               end
                        end
                        end
+
                        BuildCommServer.send_end(req)
                        BuildCommServer.disconnect(req)
 
                        BuildCommServer.send_end(req)
                        BuildCommServer.disconnect(req)
 
@@ -244,6 +433,45 @@ class SocketJobRequestListener
                        BuildCommServer.send(req,"#{@parent_server.host_os},#{@parent_server.jobmgr.max_working_jobs}")
                        BuildCommServer.send_end(req)
                        BuildCommServer.disconnect(req)
                        BuildCommServer.send(req,"#{@parent_server.host_os},#{@parent_server.jobmgr.max_working_jobs}")
                        BuildCommServer.send_end(req)
                        BuildCommServer.disconnect(req)
+               when "PROJECT"
+                       BuildCommServer.send_begin(req)
+                       # print GIT projects
+                       sorted_list = @parent_server.prjmgr.projects.sort { |x,y| x.name <=> y.name }
+                       sorted_list.each do |prj|
+                               if prj.type != "GIT" then next end 
+                               BuildCommServer.send(req,"G,#{prj.name},#{prj.repository},#{prj.branch}")
+                       end
+                       # print BINARY projects
+                       sorted_list.each do |prj|
+                               if prj.type != "BINARY" then next end 
+                               BuildCommServer.send(req,"B,#{prj.name},#{prj.pkg_name}")
+                       end
+                       # print REMOTE project
+                       sorted_list.each do |prj|
+                               if prj.type != "REMOTE" then next end 
+                               BuildCommServer.send(req,"R,#{prj.name}")
+                       end
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
+               when "OS"
+                       BuildCommServer.send_begin(req)
+                       # 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"
+                       BuildCommServer.send_begin(req)
+                       # print GIT projects
+                       @parent_server.friend_servers.each do |server|
+                               BuildCommServer.send(req,"#{server.status},#{server.host_os},#{server.waiting_jobs.length},#{server.working_jobs.length},#{server.max_working_jobs},#{server.get_file_transfer_cnt}")
+                       end
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
                else
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
                else
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
@@ -251,9 +479,83 @@ class SocketJobRequestListener
        end
 
 
        end
 
 
+       # "CANCEL"
+       def handle_cmd_cancel( 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}"
+               end
+               cancel_job = nil
+
+               #CANCEL, JOB
+               @parent_server.jobmgr.jobs.each do |j|
+                       if "#{j.id}" == "#{tok[1]}" then
+                               cancel_job = j
+                               break
+                       end
+               end
+
+               BuildCommServer.send_begin(req)
+               if cancel_job.nil? then
+                       BuildCommServer.send(req, "There is no job \"#{tok[1]}\"")
+                       raise "There is no job \"#{tok[1]}\""
+               else
+                       if cancel_job.cancel_state == "NONE" then
+                       # check passwd
+                       if cancel_job.type == "MULTIBUILD" then
+                               cancel_job.sub_jobs.select{|x| x.cancel_state == "NONE" }.each do |sub|
+                                       if not check_project_password( sub.get_project, tok[2], req) then
+                                               BuildCommServer.send(req, "Project's password is not matched!!")
+                                               raise "Project's password is not matched!!"
+                                       end
+                               end
+
+                               BuildCommServer.send(req, "\"#{cancel_job.id}, #{cancel_job.sub_jobs.map{|x| x.id}.join(", ")}\" will be canceled")
+                               cancel_job.cancel_state = "INIT"
+                       else
+                               if not check_project_password( cancel_job.get_project, tok[2], req) then
+                                       BuildCommServer.send(req, "Project's password is not matched!!")
+                                       raise "Project's password is not matched!!"
+                               else
+                                       BuildCommServer.send(req, "\"#{cancel_job.id}\" will be canceled")
+                                       cancel_job.cancel_state = "INIT"
+                               end
+                       end
+                       else
+                               BuildCommServer.send(req, "\"#{cancel_job.id}\" is already canceled")
+                       end
+               end
+               BuildCommServer.send_end(req)
+               BuildCommServer.disconnect(req)
+       end
+
+
        # "STOP"
        def handle_cmd_stop( line, req )
        # "STOP"
        def handle_cmd_stop( line, req )
-               tok = line.split(",").map { |x| x.strip }
+               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}"
+               end
+       
+               BuildCommServer.send_begin(req)
+               if tok[1] != @parent_server.password then
+                       BuildCommServer.send(req,"Password mismatched!")
+               else
+                       BuildCommServer.send(req,"Server will be down!")
+               end
+               BuildCommServer.send_end(req)
+               BuildCommServer.disconnect(req)
+               if tok[1] == @parent_server.password then
+                       @parent_server.finish = true
+               end
+       end
+
+
+       # "UPGRADE"
+       def handle_cmd_upgrade( 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}"
                if tok.count < 2 then 
                        @log.info "Received Wrong REQ: #{line}" 
                        raise "Invalid request format is used: #{line}"
@@ -269,6 +571,306 @@ class SocketJobRequestListener
                BuildCommServer.disconnect(req)
                if tok[1] == @parent_server.password then
                        @parent_server.finish = true
                BuildCommServer.disconnect(req)
                if tok[1] == @parent_server.password then
                        @parent_server.finish = true
+                       @parent_server.upgrade = true
+               end
+       end
+
+
+       # "FULLBUILD"
+       def handle_cmd_fullbuild( 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}"
+               end
+               
+               server_passwd = tok[1]          
+
+               # check server password
+               if server_passwd != @parent_server.password then
+                       BuildCommServer.send_begin(req)
+                       BuildCommServer.send(req,"Password mismatched!")
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               else
+                       # create full build job
+                       new_job = @parent_server.prjmgr.create_new_full_build_job()
+
+                       # set logger
+                       logger = JobLog.new( new_job, req )
+                       new_job.set_logger(logger)
+                       logger.init
+
+                       # add to job
+                       @parent_server.jobmgr.add_job( new_job )
+               end
+       end
+
+
+       # "REGISTER"
+       def handle_cmd_register( 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}"
+               end
+
+               type = tok[1]
+
+               case type
+               # REGISTER|BINARY-LOCAL|local_path
+               # REGISTER|SOURCE-LOCAL|local_path
+               when "BINARY-LOCAL", "SOURCE-LOCAL"
+                       file_path = tok[2]
+                       new_job = @parent_server.jobmgr.create_new_register_job( file_path )
+                       logger = JobLog.new( new_job, req )
+                       new_job.set_logger(logger)
+                       logger.init
+
+                       # add
+                       @parent_server.jobmgr.add_job( new_job )
+
+               # REGISTER|BINARY|filename|passwd
+               when "BINARY"
+                       # parse
+                       filename = tok[2]
+                       passwd = tok[3]
+                       dock = (tok[4].nil? or tok[4].empty?) ? "0" : tok[4].strip
+
+                       # check project
+                       prj = check_project_for_package_file_name(filename, req)
+                       if prj.nil? then
+                               raise "No project is defined for this binary : #{filename}!"
+                       end
+       
+                       # check passwd
+                       if not check_project_password(prj, passwd, req) then
+                               raise "Project's password is not matched!!"
+                       end
+                       
+                       # create new job
+                       @log.info "Received a request for uploading binaries : #{filename}"
+                       new_job = create_new_upload_job( prj.name, filename, dock, req )
+                       if new_job.nil? then
+                               raise "Creating build job failed : #{prj.name}, #{filename}"
+                       end
+
+                       # create logger and set
+                       logger = JobLog.new( new_job, req )
+                       new_job.set_logger(logger)
+                       logger.init
+               
+                       # 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}"
+               end
+       
+       end
+
+
+       # "UPLOAD"
+       def handle_cmd_upload( line, req )
+               @log.info "Received File transfer REQ : #{line}"
+
+               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}"
+               end
+
+               dock_num = tok[1].strip
+
+               BuildCommServer.send_begin(req)
+               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)
+       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 }
+               if tok.count < 3 then 
+                       @log.info "Received Wrong REQ: #{line}" 
+                       raise "Invalid request format is used: #{line}"
+               end
+
+               dock_num = 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}"
+               BuildCommServer.send_begin(req)
+               @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" 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)
+       end
+
+
+
+       private
+       def check_project_exist(project_name, req)
+               prj = @parent_server.prjmgr.get_project(project_name)
+               if prj.nil? then
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: Requested project does not exist!"
+                       req.puts "Info: Check project name using \"query\" command option !"
+                       BuildCommServer.send_end(req)
+                       return nil
+               end
+
+               return prj 
+       end
+
+       private
+       def check_project_for_package_file_name(filename, 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)
+               if prj.nil? then
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: Requested project does not exist!"
+                       req.puts "Info: Check project name using \"query\" command option !"
+                       BuildCommServer.send_end(req)
+                       return nil
+               end
+
+               return prj 
+       end
+
+
+       private
+       def check_project_password(prj, passwd, req)
+
+               if prj.is_passwd_set? and not prj.passwd_match?(passwd) then
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: Project's password is not matched!"
+                       req.puts "Error: Use -w option to input your project password"
+                       BuildCommServer.send_end(req)
+                       return false
+               end
+
+               return true
+       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
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: There is no OS supported by the build server."
+                       BuildCommServer.send_end(req)
+                       return nil
+               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
+                       else 
+                               if not @parent_server.supported_os_list.include?(os) then
+                                       BuildCommServer.send_begin(req)
+                                       req.puts "Error: Unsupported OS name \"#{os}\" is used!"
+                                       req.puts "Error: Check the following supported OS list. "
+                                       @parent_server.supported_os_list.each do |os_name|
+                                               req.puts " * #{os_name}"
+                                       end
+                                       BuildCommServer.send_end(req)
+                                       return nil
+                               else
+                                       result.push os
+                               end
+                       end
+               end
+
+               if result.empty? then
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: There is no OS supported by the build server."
+                       BuildCommServer.send_end(req)
+                       return nil
+               end
+
+               result.uniq!
+
+               return result
+       end
+
+
+       private
+       def create_new_job( project_name, os )
+               return @parent_server.prjmgr.create_new_job(project_name, os)
+       end
+
+
+       private
+       def create_new_upload_job( project_name, filename, dock, req)
+
+               new_job = @parent_server.prjmgr.get_project(project_name).create_new_job(filename, dock)
+
+               if new_job.nil?  then
+                       BuildCommServer.send_begin(req)
+                       req.puts "Error: Creating job failed: #{project_name} #{filename}"
+                       BuildCommServer.send_end(req)
+                       return nil
                end
                end
+
+               return new_job
+       end
+
+
+       private
+       def create_new_internal_job( git_repos, os, git_commit, pkg_files, dock_num )
+               prj = @parent_server.prjmgr.get_git_project( git_repos )
+               if prj.nil? then
+                       prj = @parent_server.prjmgr.create_unnamed_git_project( git_repos )
+               end
+               new_job = prj.create_new_job(os)
+               new_job.set_internal_job( dock_num ) 
+               new_job.set_git_commit(git_commit)
+               incoming_dir = "#{@parent_server.transport_path}/#{dock_num}"
+               pkg_files.each { |file|
+                       new_job.add_external_package( file )
+               }
+
+               return new_job
        end
 end
        end
 end
index a9e672cff3a347c13fed5903560e0e5031357079..f0087fef4099e446f8745869f2ad2068e99e89f1 100644 (file)
@@ -36,22 +36,24 @@ require "log"
 
 class Builder
        private_class_method :new
 
 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
 
        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
                @id = id
                @pkgserver_url = pkgserver_url
                @host_os = Utils::HOST_OS
+               @buildroot_dir = buildroot_dir
+               @cache_dir = cache_dir
                @log = Log.new(log_path)
        end
 
        
        # create
                @log = Log.new(log_path)
        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
 
                # check builder config root
                check_builder_config_root
@@ -61,8 +63,24 @@ class Builder
                        FileUtils.rm_rf "#{CONFIG_ROOT}/#{id}"
                end
 
                        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
                # 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] )
 
                # write config
                write_builder_config( @@instance_map[id] )
@@ -83,6 +101,18 @@ class Builder
        end
 
 
        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 )
 
        # get
        def self.get( id )
 
@@ -106,55 +136,59 @@ class Builder
        # clean
        def clean( src_path )
 
        # clean
        def clean( src_path )
 
-               build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot"
-
-               # 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
-
-               return true
+               return clean_project_directory( src_path, nil )
        end
 
 
        # build
        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
 
                # create pkginfo
-        pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
-
-               # 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" )
+               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
 
                        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"
+               # read pkginfo 
+               begin
+                       pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       return false
                end
 
                end
 
-        FileUtils.mkdir_p build_root_dir
+               # set default build os 
+               build_host_os = @host_os
 
 
-        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
+               # 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 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)
 
                # create client
                @log.info( "Downloding client is initializing...", Log::LV_USER)
@@ -162,12 +196,17 @@ class Builder
                if clean then 
                        cl.clean(true)
                end
                if clean then 
                        cl.clean(true)
                end
-        cl.update
+
+               # get local repository path list
+               repos_paths = []
+               local_pkgs.each { |path| 
+                       repos_paths.push File.dirname(path)
+               }
+               repos_paths.uniq!
 
                # install build dependencies
 
                # install build dependencies
-        package_overwrite_list = []
                @log.info( "Installing dependent packages...", Log::LV_USER)
                @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
                        if dep.target_os_list.count != 0 then
                                dep_target_os = dep.target_os_list[0]
                        else
@@ -177,73 +216,52 @@ class Builder
 
             # get local dependent package 
             pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$")
 
             # get local dependent package 
             pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$")
-            package_overwrite_list += local_pkg_list.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
+            local_dep_pkgs = local_pkgs.select{|l| l =~ pkgexp}
+
+                       # 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 pacakge...#{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
 
                        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)
                @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)
+               src_archive_list = []
+        pkginfo.get_source_dependencies(os,build_host_os).each do |dep|
+                       src_archive_list.push dep.package_name
+        end
+               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
                 return false
             end
-        end
+               end
 
                # make clean
                @log.info( "Make clean...", Log::LV_USER)
 
                # 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 )
-               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)
+               if not clean_project_directory( src_path, os ) then
                        return false
                end
 
                        return false
                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)
-                       return false
-               end
-
-               # execute build script
                @log.info( "Make build...", Log::LV_USER)
                @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
                        return false
                end
-               
                # execute install script
                @log.info( "Make install...", Log::LV_USER)
                # 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
 
                        return false
                end
 
@@ -256,37 +274,12 @@ class Builder
 
                # zip
                @log.info( "Zipping...", Log::LV_USER)
 
                # 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
                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
 
 
        end
 
 
@@ -307,15 +300,17 @@ class Builder
        def self.write_builder_config( obj )
                # create config folder
                builder_dir = "#{CONFIG_ROOT}/#{obj.id}"
        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}"
 
                # 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
                end
-               puts "#{builder_dir}/builder.cfg"
        end
 
 
        end
 
 
@@ -326,6 +321,8 @@ class Builder
                # read configuration
                builder_dir = "#{CONFIG_ROOT}/#{id}"
         log_path = nil
                # read configuration
                builder_dir = "#{CONFIG_ROOT}/#{id}"
         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=")
                File.open( "#{builder_dir}/builder.cfg", "r" ) do |f|
                        f.each_line do |l|
                                if l.start_with?("PSERVER_URL=")
@@ -333,6 +330,10 @@ class Builder
                 elsif l.start_with?("LOG-PATH=")
                     log_path = l.split("=")[1].strip 
                     log_path = nil if log_path == "STDOUT" 
                 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 
                                else
                                        next    
                                end 
@@ -340,151 +341,137 @@ class Builder
                end
 
         if log_path.empty? then log_path = nil end
                end
 
         if log_path.empty? then log_path = nil end
+
                # create object & return it
                # create object & return it
-               return new( id, pkgserver_url, log_path )
+               return new( id, pkgserver_url, log_path, buildroot_dir, cache_dir )
        end
 
 
        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
+       # execute build command
+       def execute_build_command( target, src_path, build_root_dir, os, version )
 
 
-               return reverse_fail_list.uniq
-       end
+               # get category 
+               os_category = Utils.get_os_category( os )
 
 
+               # 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
 
 
-       # build test
-       def build_test_with_pkg_client( pkg_cl, src_path, os,  parent_path)
+               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
 
 
-        local_pkg_list = []
-        local_pkg_list += Dir.entries(parent_path).select{|e| e =~ /\.zip$/}.map{|p| parent_path + "/" + p}
+               # 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
 
 
-               # create pkginfo
-        pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
+               # 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
 
 
-               # 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]
+                       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
                        else
-                               dep_target_os = os
+                               @log.warn( "Wrong build-target is used: \"#{target}\"", 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}
-
-            pkg_cl.install(dep.package_name, dep_target_os, true, false)
-               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 
-
-               # source download
-               pkginfo.get_source_dependencies(os,@host_os).each do |dep|
-            pkg_cl.download_dep_source(dep.package_name)
+                       f.puts "#{target}"
+                       f.puts "echo \"success\""
                end
                end
+               Utils.execute_shell_with_log( "chmod +x #{src_path}/.build.sh", @log )
+        build_command = "cd \"#{src_path}\";" + env_def + "./.build.sh"
 
 
-               # 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"
+               # execute script
                if not Utils.execute_shell_with_log( build_command, @log ) then
                if not Utils.execute_shell_with_log( build_command, @log ) then
-                       @log.error( "Failed on build script", Log::LV_USER)
+                       @log.error( "Failed on build script: \"#{target}\"", Log::LV_USER)
                        return false
                else
                        return false
                else
+                       Utils.execute_shell_with_log( "rm -rf #{src_path}/.build.sh", @log )
                        return true
                end
                        return true
                end
-
        end
 
 
        end
 
 
-       # write pkginfo.manifest and install/remove script
+       # write pkginfo.manifest
        def     write_pkginfo_files(pkginfo,os,src_path)
        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
                        # skip if not support the target os
-                       if not pkg.os.include? os
+                       if not pkg.os_list.include? os
                                next
                        end
 
                                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}"
 
                        # 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
                        # 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)
+                                       return false
+                               end
                        end
                        end
-               
-                       # write pkginfo.manifest        
+
+                       # write pkginfo.manifest
                        File.open("#{install_dir}/pkginfo.manifest", "w") do |f|
                        File.open("#{install_dir}/pkginfo.manifest", "w") do |f|
-                               pkg.print_to_file_with_os( f, os )
+                               pkg.print_to_file( f )
                        end
                end
 
                        end
                end
 
@@ -494,74 +481,207 @@ class Builder
 
        # copy post-install script
        def     copy_post_install_script(pkg,os,src_path)
 
        # copy post-install script
        def     copy_post_install_script(pkg,os,src_path)
-               
+
                tar = nil
                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)
+                               return false
+                       end
                end
 
                if not src.nil? then
                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} "
                        else
                                puts "Unknown OS: #{os} "
-                               return
+                               return true
                        end
 
                        FileUtils.cp(src, tar)
                        end
 
                        FileUtils.cp(src, tar)
-               end     
-       
-               return
+               end
+
+               return true
        end
 
 
        # copy post-remove script
        def     copy_post_remove_script(pkg,os,src_path)
        end
 
 
        # copy post-remove script
        def     copy_post_remove_script(pkg,os,src_path)
-               
+
                tar = nil
                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)
+                               return false
+                       end
                end
 
                if not src.nil?
                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} "
                        else
                                puts "Unknown OS: #{os} "
-                               return
+                               return true
                        end
 
                        FileUtils.cp(src, tar)
                        end
 
                        FileUtils.cp(src, tar)
-               end     
+               end
+               return true
        end
 
 
        # create package file
        def     make_zip(pkginfo,os,src_path)
        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
                        # 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}"
                                next
                        end
 
                        # cd install dir
                        install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}"
+                       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)
+                                       return false
+                               end
+                       end
                        
                        # zip   
                        @log.info( "Creating package file ... #{pkg.package_name}_#{pkg.version}_#{os}.zip", Log::LV_USER)
                        
                        # 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 *")
+                       @log.info("cd \"#{install_dir}\"; zip -r -y #{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip *")
+                       Utils.execute_shell_with_log("cd \"#{install_dir}\"; zip -r -y #{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip *", @log)
+                       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
                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
        end
 end
index 31611fcf37f46c895bb5d81430b923e303ce6bc4..b2f5ad85f6b39d09d9bdfda5ab1896c2e246b803 100644 (file)
@@ -28,17 +28,27 @@ Contributors:
 
 require 'optparse'
 require 'logger'
 
 require 'optparse'
 require 'logger'
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+require "utils"
 
 def parse()
 
     #option parsing 
     option = {}
 
 def parse()
 
     #option parsing 
     option = {}
-    optparse = OptionParser.new do |opts|
-        opts.banner = "Usage: pkg-clean"
-        opts.on('-h','--help', 'display this information') do 
+    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 
             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!
     end 
 
     optparse.parse!
index 05888f0254485cdfaad3ec38148bdf0efdaea67e..3f23fc328139cd9d23f9b8c77fd11ca674da34fd 100644 (file)
@@ -28,35 +28,53 @@ Contributors:
 
 require 'optparse'
 require 'logger'
 
 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|
 
 def parse()
 
     #option parsing 
     option = {}
     optparse = OptionParser.new do |opts|
-        opts.banner = "Usage: pkg-build -u <remote_package_server_url> -o <os> -c -h"
-        opts.on('-u','--url <remote_package_server_url>', 'remote package server url') do |url|
+        opts.banner = "Build and packaging service command-line tool." + "\n" \
+               + "\n" + "Usage: pkg-build -u <package server url> [-o <os>] [-c] [-h] [-v]" + "\n" \
+               + "\n" + "Options:" + "\n"
+
+        opts.on('-u','--url <package server url>', 'remote package server url: http://127.0.0.1/dibs/unstable') do |url|
             option[:url] = url
         end 
             option[:url] = url
         end 
+
         option[:os] = nil
         opts.on('-o','--os <os>', 'operating system ') do |os|
             option[:os] = os
         option[:os] = nil
         opts.on('-o','--os <os>', 'operating system ') do |os|
             option[:os] = os
-        end 
+        end
+
         option[:clean] = false
         opts.on('-c','--clean', 'clean build') do 
             option[:clean] = true
         option[:clean] = false
         opts.on('-c','--clean', 'clean build') do 
             option[:clean] = true
-        end 
+        end
+
         option[:rev] = false
         option[:rev] = false
-        opts.on('-r','--rev', 'reverse build dependency check') do 
-            option[:rev] = true
-        end 
-        opts.on('-h','--help', 'display this information') do 
+        #opts.on('-r','--rev', 'reverse build dependency check') do 
+        #    option[:rev] = true
+        #end 
+
+        opts.on('-h','--help', 'display help') do
             puts opts
             exit
             puts opts
             exit
+        end
+
+        opts.on('-v','--version', 'display version') do 
+            puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
+            exit
         end 
         end 
-    end 
+    end
 
     optparse.parse!
 
     optparse.parse!
+
+    if option[:url].nil? or option[:url].empty? then
+        raise ArgumentError, "Usage: pkg-build -u <package server url> [-o <os>] [-c] [-h]"
+    end
  
  
-   return option
+    return option
 end 
 end 
diff --git a/src/common/Action.rb b/src/common/Action.rb
new file mode 100644 (file)
index 0000000..7b64559
--- /dev/null
@@ -0,0 +1,47 @@
+=begin
+ Action.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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
index 4a9c2d3f6aa0a4316d41003d3d3342725e3b15b8..044b7b6b5a62955bc9086a6db1dd5bfb4b60fd5a 100644 (file)
@@ -33,30 +33,23 @@ class PackageManifest
        attr_accessor :packages
 
        def initialize( file_path )
        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
        end
 
 
        # scan all build dependencies
-       def get_build_dependencies( target_os, host_os )
+       def get_build_dependencies( target_os )
                # for all
                list = []
                # for all
                list = []
-               for pkg in @packages
+               @packages.each do |pkg|
                        # package that has the target os
                        # package that has the target os
-                       if not pkg.os.include?(target_os)
+                       if not pkg.os_list.include?(target_os)
                                next
                        end
 
                                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
                        # 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!
                        end
                end
                list.uniq!
@@ -65,13 +58,13 @@ class PackageManifest
        end     
 
        
        end     
 
        
-       # scan all build dependencies
+       # scan all source dependencies
        def get_source_dependencies( target_os, host_os )
                # for all
                list = []
        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
                        # only package that used in target os
-                       if not pkg.os.include?(target_os)
+                       if not pkg.os_list.include?(target_os)
                                next
                        end
 
                                next
                        end
 
@@ -81,7 +74,7 @@ class PackageManifest
                        end
 
                        # package that has the target os
                        end
 
                        # package that has the target os
-                       for dep in pkg.source_dep_list
+                       pkg.source_dep_list.each do |dep|
                        #       if dep.target_os_list.include? target_os
                                        list.push dep
                        #       end
                        #       if dep.target_os_list.include? target_os
                                        list.push dep
                        #       end
@@ -93,10 +86,32 @@ class PackageManifest
        end     
 
 
        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     
+
+
        def package_exist?(target_os, host_os)
        def package_exist?(target_os, host_os)
-               for pkg in @packages
+               @packages.each do |pkg|
                        # only package that used in target os
                        # 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
                                pkg.build_host_os.include?(host_os)
                                return true
                        end
@@ -104,4 +119,34 @@ class PackageManifest
 
                return false
        end     
 
                return false
        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
 end
diff --git a/src/common/ScheduledActionHandler.rb b/src/common/ScheduledActionHandler.rb
new file mode 100644 (file)
index 0000000..a62c5f0
--- /dev/null
@@ -0,0 +1,99 @@
+=begin
+ ScheduledActionHandler.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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__)
+
+class ScheduledActionHandler 
+       attr_accessor :quit
+
+       # init
+       def initialize( )
+               @thread = nil
+               @quit = false
+               @actions = []
+       end
+
+
+       # register a action
+       def register( action )
+               # init action
+               action.init
+               # add to list
+               @actions.push action
+       end
+
+
+       # start thread
+       def start()
+               @thread = Thread.new {
+                       # main
+                       thread_main()
+                       
+                       # close 
+                       terminate()
+               } 
+       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
+                                               @actions.delete(action) 
+                                       end
+                               end
+                       end
+
+                       # sleep 10 sec
+                       sleep 10                        
+               end
+       end
+
+
+       def terminate
+       end
+
+end
index 3bdba12f97cf8d6d2c8eb394ecd3ee7e3fcad8cb..633d3784b1967b8183d7961164c5d5b16a800b47 100644 (file)
@@ -45,5 +45,10 @@ class Version < Array
        end   
        def == x     
                (self <=> x) == 0   
        end   
        def == x     
                (self <=> x) == 0   
+       end
+       def compare x
+               if self < x      then return -1
+               elsif self == x then return 0
+               else return 1 end
        end 
 end 
        end 
 end 
diff --git a/src/common/fileTransfer.rb b/src/common/fileTransfer.rb
new file mode 100644 (file)
index 0000000..cda6a4b
--- /dev/null
@@ -0,0 +1,118 @@
+
+require 'socket'
+
+class FileTransfer
+
+    def FileTransfer.putfile(ip, port, username, passwd, bpath, logger)
+        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
+                       logger.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)
+                       logger.info "[FTP log] Put a file"
+                       logger.info "[FTP log]   from \"#{bpath}\" to \"#{ftp_filepath}\""                      
+                       files = ftp.list(filename)
+                       if files.empty? then 
+                               logger.error "[FTP log] Failed to upload file (#{filename} does not exist)"
+                               return nil      
+                       end
+            ftp.quit
+                       logger.info "[FTP log] Disconnected FTP server"
+        rescue => e
+                       logger.error "[FTP log] Exception"
+                       logger.error e.message
+                       logger.error e.backtrace.inspect
+                       return nil                      
+        end
+               return ftp_filepath
+    end
+
+    def FileTransfer.getfile(ip, port, username, passwd, bpath, target, logger)
+        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                
+                       logger.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)
+                       logger.info "[FTP log] Get a file"
+                       logger.info "[FTP log]   from \"#{bpath}\" to \"#{dst_file}\""
+            ftp.quit
+                       logger.info "[FTP log] Disconnected FTP server"
+        rescue => e
+                       logger.error "[FTP log] Exception"
+                       logger.error e.message
+                       logger.error e.backtrace.inspect
+                       return nil                      
+               end
+               if not File.exist? dst_file then
+                       logger.error "[FTP log] Failed to download file (#{dst_file} does not exist)"
+                       return nil
+               end                             
+        return bpath
+    end
+
+    def FileTransfer.cleandir(ip, port, username, passwd, path, logger)
+        dirname = File.dirname(path)
+
+        begin
+            ftp = Net::FTP.new
+            if port.nil? or port == "" then
+                ftp.connect(ip)
+            else
+                ftp.connect(ip, port)                    
+            end                    
+                       logger.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)
+                       logger.info "[FTP log] Clean dir (#{dirname})"                  
+            ftp.quit
+                       logger.info "[FTP log] Disconnected FTP server"
+        rescue => e
+                       logger.error "[FTP log] Exception"
+                       logger.error e.message
+                       logger.error e.backtrace.inspect
+                       return nil                      
+        end
+
+        return true
+       end
+end
index afa8fd794d52e232cb016cb280cfc971c032f46f..e7eb19041e2549bfd60060eef09d5b131bf0c89e 100644 (file)
@@ -30,7 +30,7 @@ require "logger"
 
 class Log
 
 
 class Log
 
-       attr_accessor :path
+       attr_accessor :path, :cnt
 
        # Log LEVEL
        LV_NORMAL = 1
 
        # Log LEVEL
        LV_NORMAL = 1
@@ -39,6 +39,7 @@ class Log
 
        # init
        def initialize(path, lv=LV_USER)
 
        # init
        def initialize(path, lv=LV_USER)
+               @cnt = 0
         @path = path
                if @path.nil? then
                        @logger = Logger.new(STDOUT)
         @path = path
                if @path.nil? then
                        @logger = Logger.new(STDOUT)
@@ -52,43 +53,47 @@ class Log
                # diable logger format
                @default_formatter = @logger.formatter
                @no_prefix_formatter = proc do |severity, datetime, progname, msg|
                # 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)
                end
        end
 
 
        def info(msg, lv=LV_NORMAL)
-        if @path.nil? then puts "Info: #{msg}"
+        if @path.nil? and not @second_out.nil? then puts "Info: #{msg}"
         else @logger.info msg end
         else @logger.info msg end
-               if not @second_out.nil? and lv >= @second_out_level then 
-                       output_extra "Info: " + msg 
+               if not @second_out.nil? and lv >= @second_out_level then
+                       output_extra "Info: " + msg
                end
                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
                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
-       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
                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
                end
+               @cnt = @cnt + 1
        end
 
 
        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
                else @logger.info msg end
                if not @second_out.nil? and lv >= @second_out_level then
-                       output_extra msg 
+                       output_extra msg
                end
                end
+               @cnt = @cnt + 1
        end
 
 
        end
 
 
@@ -99,7 +104,6 @@ class Log
 
        protected
        def output_extra(msg)
 
        protected
        def output_extra(msg)
-               #do nothing     
-       end     
-
+               #do nothing
+       end
 end
 end
index 122f97709088c6ef4e312b00ffe707b5b8f7528a..067342a657788ac1778dcbcc45242d45794bf48b 100644 (file)
@@ -1,6 +1,6 @@
 =begin
 =begin
- package.rb 
+
+ package.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -27,11 +27,13 @@ Contributors:
 =end
 
 class Package
 =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
+    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
     def initialize (package_name)
         @package_name = package_name
     def initialize (package_name)
         @package_name = package_name
+        @label = ""
         @version = ""
         @os = ""
         @version = ""
         @os = ""
+        @os_list = []
         @build_host_os = []
         @maintainer = ""
         @attribute = []
         @build_host_os = []
         @maintainer = ""
         @attribute = []
@@ -46,116 +48,45 @@ class Package
         @checksum = ""
         @size = ""
         @description = ""
         @checksum = ""
         @size = ""
         @description = ""
-    end 
+               @custom = ""
+    end
+
     def print
     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 
+        puts self.to_s
+    end
 
     def to_s
         string =  "Package : " + @package_name
 
     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 
+        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(", ")
             string = string + "\n" + "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @build_dep_list.empty? then 
+        end
+        if not @build_dep_list.empty? then
             string = string + "\n" + "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
             string = string + "\n" + "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source_dep_list.empty? then 
+        end
+        if not @source_dep_list.empty? then
             string = string + "\n" + "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
             string = string + "\n" + "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @conflicts.empty? then 
+        end
+        if not @conflicts.empty? then
             string = string + "\n" + "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ")
             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
+        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
 
     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 
+    def print_to_file(file)
+        file.puts self.to_s
     end
     end
-end 
+end
index 01f7acf6c36aa1bcac3849b6f015933797efc5e1..8bb863d24686d16588ab10cf1f2388715bd91e13 100644 (file)
@@ -1,6 +1,6 @@
 =begin
 =begin
- parser.rb 
+
+ parser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -31,172 +31,304 @@ require "package"
 require "dependency"
 
 class Parser
 require "dependency"
 
 class Parser
-    def Parser.read_pkginfo_list (file)
-        pkglist = {}
+    def Parser.read_multy_pkginfo_from (file, only_common = false)
+        pkglist = []
+               package = nil
+
+               #file check
+
         File.open file,"r" do |f|
             #variable initialize
         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 = ""
-
+                       state = "INIT"
+                       common_source = ""
+                       common_version = ""
+                       common_maintainer = ""
             f.each_line do |l|
                 # separator
             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 
+                               if l.strip.empty? then
+                                       #make package and initialize
+                                       if state == "PACKAGE" then
+                                               if not package.package_name.empty? then
+                                                       pkglist.push package
+                                               else
+                                                       raise RuntimeError, "#{file} format is not valid"
+                                               end
+                                       end
+                                       state = "INIT"
+                                       package = nil
+                                       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
+                                       if only_common then return [common_source, common_version, common_maintainer] end
+                                       # state control
+                                       case state
+                                       when "INIT" then state = "PACKAGE"
+                                       when "COMMON" then state = "PACKAGE"
+                                       when "PACKAGE" then
+                                               if not package.package_name.empty? then
+                                                       pkglist.push package
+                                               else
+                                                       raise RuntimeError, "Package name is not set in \"#{file}\" file"
+                                               end
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       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
+                                       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
+                                       disc_on=false
+                               when /^Label/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Label field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.label = l.sub(/^[ \t]*Label[ \t]*:[ \t]*/i,"").strip
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Version/i then
+                                       case state
+                                       when "INIT" , "COMMON" then
+                                               if common_version.empty? then
+                                                       common_version = l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip
+                                               else
+                                                       raise RuntimeError, "Version information is conflict in \"#{file}\" file\nIf use Version field in Common section then Package section can't contain Version field"
+                                               end
+                                       when "PACKAGE" then
+                                               if common_version.empty? then
+                                                       package.version = l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip
+                                               else
+                                                       raise RuntimeError, "Version information is conflict in \"#{file}\" file\nIf use Version field in Common section then Package section can't contain Version field"
+                                               end
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^OS/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support OS field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then 
+                                               package.os_list = l.sub(/^[ \t]*OS[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split(",")
+                                               package.os = package.os_list[0]
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Build-host-os/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Build-host-os field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.build_host_os = l.sub(/^[ \t]*Build-host-os[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split(",")
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Maintainer/i then
+                                       case state
+                                       when "INIT" , "COMMON" then
+                                               if common_maintainer.empty? then
+                                                       common_maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip
+                                               else
+                                                       raise RuntimeError, "Maintainer information is conflict in \"#{file}\" file\nIf use Maintainer field in Common section then Package section can't contain Maintainer field"
+                                               end
+                                       when "PACKAGE" then
+                                               if common_maintainer.empty? then
+                                                       package.maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip
+                                               else
+                                                       raise RuntimeError, "Maintainer information is conflict in \"#{file}\" file\nIf use Maintainer field in Common section then Package section can't contain Maintainer field"
+                                               end
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Attribute/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Attribute field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.attribute = l.sub(/^[ \t]*Attribute[ \t]*:[ \t]*/i,"").tr(" \t\n\r","").split("|")
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Install-dependency/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Install-dependency field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.install_dep_list = dep_parser l.sub(/^[ \t]*Install-dependency[ \t]*:[ \t]*/i,"").split(',')
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Build-dependency/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Build-dependency field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.build_dep_list = dep_parser l.sub(/^[ \t]*Build-dependency[ \t]*:[ \t]*/i,"").split(',')
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Source-dependency/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Source-dependency field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.source_dep_list = dep_parser l.sub(/^[ \t]*Source-dependency[ \t]*:[ \t]*/i,"").split(',')
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Conflicts/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Conflicts field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.conflicts = dep_parser l.sub(/^[ \t]*Conflicts[ \t]*:[ \t]*/i,"").split(',')
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Source/i then
+                                       case state
+                                       when "INIT" , "COMMON" then
+                                               state = "COMMON"
+                                               if common_source.empty? then
+                                                       common_source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip
+                                               else
+                                                       raise RuntimeError, "Source information is conflict in \"#{file}\" file\nIf use Source field in Common section then Package section can't contain Source field"
+                                               end
+                                       when "PACKAGE" then
+                                               if common_source.empty? then
+                                                       package.source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip
+                                               else
+                                                       raise RuntimeError, "Source information is conflict in \"#{file}\" file\nIf use Source field in Common section then Package section can't contain Source field"
+                                               end
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Src-path/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Src-path field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then
+                                               package.src_path = l.sub(/^[ \t]*Src-path[ \t]*:[ \t]*/i,"").strip
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^ORIGIN/ then
+                                       #for compatable
+                                       next
+                               when /^Include/i then
+                                       case state
+                                       when "INIT", "COMMON" then
+                                               pfile = File.dirname(file) + "/" + l.sub(/^[ \t]*Include[ \t]*:[ \t]*/i,"").strip
+                                               if File.exist? pfile then
+                                                       pkglist = Parser.read_multy_pkginfo_from pfile
+                                                       list = Parser.read_multy_pkginfo_from(pfile, true)
+                                                       common_source = list[0]
+                                                       common_version = list[1]
+                                                       common_maintainer = list[2]
+                                               else
+                                                       raise RuntimeError, "Not exist \"#{pfile}\""
+                                               end
+                                       when "PACKAGE" then raise RuntimeError, "Not support Include field in Common section in \"#{file}\" file"
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Path/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Path field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.path = l.sub(/^[ \t]*Path[ \t]*:[ \t]*/i,"").strip
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Origin/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Origin field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.origin = l.sub(/^[ \t]*Origin[ \t]*:[ \t]*/i,"").strip
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^SHA256/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support SHA256 field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.checksum = l.sub(/^[ \t]*SHA256[ \t]*:[ \t]*/i,"").strip
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Size/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Size field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.size = l.sub(/^[ \t]*Size[ \t]*:[ \t]*/i,"").strip
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               when /^Description/i then
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Description field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then package.description = l.sub(/^[ \t]*Description[ \t]*:[ \t]*/i,"")
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=true
+                               when /^C-/ then
+                                       #custom field
+                                       case state
+                                       when "INIT" then raise RuntimeError, "\"Package :\" string must be infront of Package section in \"#{file}\" file"
+                                       when "COMMON" then raise RuntimeError, "Not support Description field in Common section in \"#{file}\" file"
+                                       when "PACKAGE" then
+                                               if package.custom.empty? then
+                                                       package.custom = l.strip
+                                               else
+                                                       package.custom = package.custom + "\n" + l.strip
+                                               end
+                                       else raise RuntimeError, "UNKNOWN parser state : #{state}"
+                                       end
+                                       disc_on=false
+                               else
+                                       if disc_on and state == "PACKAGE" then
+                                               package.description = package.description + l
+                                       else
+                                               raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}"
+                                       end
+                               end
+                       end
 
 
-    def Parser.read_pkginfo (file)
-        return read_pkg_list(file).values[0]
-    end 
+                       if only_common then return [common_source, common_version, common_maintainer] end
+
+            # check last package
+                       if state == "PACKAGE" then
+                               if not package.package_name.empty? then
+                                       pkglist.push package
+                               else
+                                       raise RuntimeError, "Package name is not set in \"#{file}\" file"
+                               end
+                       end
+               end
+               return pkglist
+       end
+
+    def Parser.read_single_pkginfo_from (file)
+        return read_multy_pkginfo_from(file)[0]
+    end
 
 
-    def Parser.read_pkg_list (file)
+    def Parser.read_repo_pkg_list_from (file)
         result = {}
         result = {}
-        read_pkginfo_list(file).values.each { |x| result[x.package_name]=x }
+        read_multy_pkginfo_from(file).each { |x| result[x.package_name]=x }
         return result
         return result
-    end 
+    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)
 
     private
     def Parser.dep_parser (string_list)
@@ -208,7 +340,7 @@ class Parser
             base_version = nil
             target_os_list = []
             #string trim
             base_version = nil
             target_os_list = []
             #string trim
-            dependency = dep.tr " \t\n", ""
+            dependency = dep.tr " \t\r\n", ""
             #version extract
             vs = dependency.index('(') 
             ve = dependency.index(')') 
             #version extract
             vs = dependency.index('(') 
             ve = dependency.index(')') 
index 24b12ff0dc7fb5a267321e0bbcd7f139a9a2c256..ea2bf959661ab6f9315f819f620d03d17affdfdc 100644 (file)
@@ -27,32 +27,61 @@ Contributors:
 =end
 
 class Utils
 =end
 
 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"
                case `uname -s`.strip
                        when "Linux"
-                               HOST_OS = "linux"
-                       when /MINGW32.*/
-                               HOST_OS = "windows"
+                               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"
                        when "Darwin"
-                               HOST_OS = "darwin"
-                       else
-               end  
+                           os = "macos-64"
+               end 
+
+               return os 
        end
 
        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 
+
+       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
 
        end
 
+
     def Utils.create_uniq_name      
         time = Time.new     
     def Utils.create_uniq_name      
         time = Time.new     
+
         # uniq snapshot_name name is year_month_day_hour_min_sec_microsec       
         # uniq snapshot_name name is year_month_day_hour_min_sec_microsec       
-        return time.strftime("%m%d%H%M%S") + time.usec.to_s()        
+               return time.strftime("%m%d%H%M%S") + time.usec.to_s.rjust(6, '0')
     end
 
     def Utils.is_url_remote(url)
     end
 
     def Utils.is_url_remote(url)
@@ -109,26 +138,44 @@ class Utils
         return 0
        end
 
         return 0
        end
 
+    def Utils.execute_shell_generate(cmd, os_category = nil)
+               result_lines = []
+
+               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}\""
+               end
 
 
-    def Utils.execute_shell(cmd)
+               return cmd
+       end
+
+
+    def Utils.execute_shell(cmd, os_category = nil)
         ret = false
         ret = false
-               if HOST_OS.eql? "windows" then
+               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}\""
                end
 
                        mingw_path = "sh.exe -c "
                        cmd = cmd.gsub("\"", "\\\"")
             cmd = mingw_path + "\"#{cmd}\""
                end
 
-               system "#{cmd}"
+               `#{cmd}`
         if $?.to_i == 0 then ret = true else ret = false end 
                
                return ret
        end
 
 
         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 = []
 
                result_lines = []
 
-               if HOST_OS.eql? "windows" then
+               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}\""
                        mingw_path = "sh.exe -c "
                        cmd = cmd.gsub("\"", "\\\"")
             cmd = mingw_path + "\"#{cmd}\""
@@ -148,8 +195,10 @@ class Utils
                end 
        end
 
                end 
        end
 
-    def Utils.execute_shell_return_ret(cmd)
-               if HOST_OS.eql? "windows" then
+    def Utils.execute_shell_return_ret(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}\""
                        mingw_path = "sh.exe -c "
                        cmd = cmd.gsub("\"", "\\\"")
             cmd = mingw_path + "\"#{cmd}\""
@@ -158,9 +207,11 @@ class Utils
         return `#{cmd}`
     end
 
         return `#{cmd}`
     end
 
-       def Utils.execute_shell_with_log(cmd, log)
+       def Utils.execute_shell_with_log(cmd, log, os_category = nil)
 
 
-               if HOST_OS.eql? "windows" then
+               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}\""
                        mingw_path = "sh.exe -c "
                        cmd = cmd.gsub("\"", "\\\"")
             cmd = mingw_path + "\"#{cmd}\""
@@ -180,16 +231,79 @@ class Utils
                end 
        end
 
                end 
        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)
 
        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 
                        end
                        # if path start "/" then absoulte path
                        if path.start_with?("/") then
                                return true
                        else
                                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
                        # if path start "c:/" or "D:/" or ... then absoulte path
                        if path =~ /^[a-zA-Z]:[\/]/ then
                                return true
@@ -204,9 +318,9 @@ class Utils
 
        # this will be used on MinGW/MSYS
        def Utils.get_unix_path(path)
 
        # 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
                        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]
                        new_path = path
                        if is_absolute_path( new_path ) then
                                new_path = "/" + new_path[0,1] + new_path[2..-1]
@@ -217,4 +331,234 @@ class Utils
                        return path
                end
        end
                        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 `sha256sum #{file_path}`.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
+
+       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
 end
diff --git a/src/pkg_server/DistSync.rb b/src/pkg_server/DistSync.rb
new file mode 100644 (file)
index 0000000..5fb6df9
--- /dev/null
@@ -0,0 +1,98 @@
+=begin
+ DistSync.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+
+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 "packageServer.rb"
+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 (file)
index 0000000..2ad78e3
--- /dev/null
@@ -0,0 +1,213 @@
+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 "fileTransfer"
+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 {
+                       main()          
+               }
+       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 {        
+                       handle_cmd_upload( req_line, req )
+            }             
+               when "REGISTER"
+            Thread.new {        
+                               handle_cmd_register( req_line, req )
+            }             
+               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 {
+                       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
+               }
+                               
+               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 
+
index 5cf84234e3f608d3f2def4d05d3de057d60acd9e..a7e203475900b424b01466d944f47d822fc43381 100644 (file)
@@ -1,6 +1,5 @@
-
 =begin
 =begin
+
  client.rb 
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
  client.rb 
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -28,29 +27,36 @@ Contributors:
 =end
 
 require "fileutils"
 =end
 
 require "fileutils"
+require "thread"
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 $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 "downloader"
 require "installer"
+require "fileTransfer"
 require "packageServerConfig"
 require "package"
 require "parser"
 require "utils"
 require "log"
 require "Version"
 require "packageServerConfig"
 require "package"
 require "parser"
 require "utils"
 require "log"
 require "Version"
-
+require "net/ftp"
+$update_mutex = Mutex.new
+$get_snapshot_mutex = Mutex.new
+$filemove_mutex = Mutex.new
 class Client
 
     # constant
 class Client
 
     # constant
-    SUPPORTED_OS = ["linux", "windows", "darwin"]
     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"
     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
+    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
 
     public
     # initialize
@@ -64,348 +70,354 @@ class Client
 
         # set default server address, location
         if server_addr.nil? then server_addr = get_default_server_addr() 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
+               if location.nil? then location = get_default_inst_dir() end
 
         # chop server address, if end with "/"        
 
         # chop server address, if end with "/"        
-        if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end
+               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                             
 
 
-        @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)
         @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
 
         # set log
         if logger.nil? or logger.class.to_s.eql? "String" then
            @log = Log.new(logger)
         else
            @log = logger
 
         # 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)
+               end
 
         # read installed pkg list, and create hash
 
         # 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
+               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()
 
     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"
+               if not @snapshot_url then               
+                       $get_snapshot_mutex.synchronize {
+                               @snapshot_path = get_lastest_snapshot(@is_server_remote)
+                       }
+               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 {
+                               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             
+
+               $update_mutex.synchronize {
+               create_default_config(@server_addr)
+               @log.info "Update package list from \"#{@server_addr}\".. OK"
+               }
+
         return true
         return true
-    end
+       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
 
     public
     # download package
-    def download(pkg_name, os, trace)
+    def download(pkg_name, os, trace, loc = nil)
+
+               if loc.nil? then loc = @location end
 
         dependent_pkg_list = []
 
         # get dependent list
         if trace then
 
         dependent_pkg_list = []
 
         # get dependent list
         if trace then
-            dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, false)
+            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
 
             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 = nil
-        addr_arr = @server_addr.split('/')
-        if addr_arr[-2].eql? "snapshots" then
-            surl = @server_addr + "/../.."
-        else 
-            surl = @server_addr
-        end
-
+               surl = @server_addr
         # download files
         file_local_path = []
         dependent_pkg_list.each do |p|
         # 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_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 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, @location) then
-                @log.error "Failed download #{pkg_name} [#{pkg_ver}]"
-                return nil
+                       
+            if not FileDownLoader.download(url, loc, @log) then
             end
 
             end
 
-            file_path = File.join(@location, filename)
+               file_path = File.join(loc, filename)
             file_local_path.push(file_path)
             file_local_path.push(file_path)
-            @log.info "Downloaded \"#{p} [#{pkg_ver}]\" package file.. OK"
-            #@log.info "  [path : #{file_path}]"
         end
 
         if trace then
             @log.info "Downloaded \"#{pkg_name}\" package with all dependent packages.. OK"
         end
 
         if trace then
             @log.info "Downloaded \"#{pkg_name}\" package with all dependent packages.. OK"
-        else
-            @log.info "Downloaded only \"#{pkg_name}\" package.. OK"
         end
         end
-        @log.info "  [path : #{file_local_path.join(", ")}]"
+        @log.info "  [path: #{file_local_path.join(", ")}]"
 
         return file_local_path
 
         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
+       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}]"
+       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 {
+                       if not File.exist? distfile then
+                               Utils.execute_shell("mv #{filepath} #{distfile}")
+                       else 
+                               Utils.execute_shell("rm -f #{filepath}")                                
+                               return distfile 
+                       end
+               }
+
+               if File.exist? distfile then return distfile
+               else 
+                       @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                                     
 
 
-        return file_local_path
-    end
-    
     public
     # download dependent source
     def download_dep_source(file_name)
 
     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
+        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.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}]"
+        @log.info "  [path: #{file_local_path}]"
 
         return file_local_path
     end
 
 
         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
     public
     # upload package
-    def upload(ssh_alias, id, binary_path_list, source_path_list, verify)
+    def upload(ip, port, ftp_addr, ftp_port, ftp_username, ftp_passwd, binary_path_list)
 
 
-        # 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
+           # check ip and port
+           if ip.nil? or port.nil? then
+               @log.error "Ip and port should be set."
+               return nil
+           end
 
 
-        if not hostfound then
-            @log.error "\"#{ssh_alias}\" does not exist in \".ssh/config\" file"
+        # 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
 
             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"
-               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
-                       end
-        end
-        pkg_svr = "#{server_home}/tizen_sdk/dev_tools/pkg-svr"
+               # create unique dock number
+               dock = Utils.create_uniq_name()
 
 
-        # set incoming directory (~/.build_tools/pkg_server/#{id}/incoming)        
-        incoming_path = "#{server_home}/.build_tools/pkg_server/#{id}/incoming"
+        # upload file
+        binary_list = []
+           binary_path_list.each do |bpath|
+            filename = File.basename(bpath)
+               client = BuildCommClient.create(ip, port, @log)
 
 
-        # set pkg-svr register command
-        register_command = "#{pkg_svr} register -i #{id} -d #{dist}"
+               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
 
 
-        # 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
-                               Utils.execute_shell("cd #{File.dirname(spath)};scp #{File.basename(spath)} #{ssh_alias}:#{server_src_pkg_path}")
-            else
-                @log.error "#{spath} file does not exist"
+            begin
+                result = client.send_file(ftp_addr, ftp_port, ftp_username, ftp_passwd, bpath)
+            rescue => e
+                @log.error "FTP failed to put file (exception)"
+                @log.error "#{e.message}"
+                @log.error e.backtrace.inspect
                 return nil
             end
                 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
+            if not result then
+                               @log.error "FTP failed to put file (result is false)"
+                return nil
+            end
 
 
-        # add src package list to register command
-        register_command = register_command + " -s #{server_src_pkg_list_command} -g"
+                       client.terminate
+            binary_list.push(filename)
+           end
 
 
-        # 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"
+        # 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
+                output = client.read_lines do |l|
+                    line = l.split("|")
+                    if line[0].strip == "ERROR" then
+                        @log.error l.strip
                         return nil
                         return nil
+                    elsif line[0].strip == "SUCC" then
+                        snapshot = line[1].strip
                     end
                 end
                     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"
+                if not output then
+                    @log.error "Failed to register"
                     return nil
                 end
                     return nil
                 end
-            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 + "\""
+                   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
+               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
+        return snapshot
     end
 
     private
     end
 
     private
@@ -415,19 +427,30 @@ class Client
         manifest_file = "pkginfo.manifest"
         uniq_name = Utils.create_uniq_name
         path = Utils::HOME + "/tmp/#{uniq_name}"
         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
+        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)
 
 
         list = get_all_reverse_install_dependent_packages_remote(pkg_name, os, true)
 
@@ -474,20 +497,36 @@ class Client
         end
 
         dist = ""
         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
+               dist = File.basename(server)
 
         return dist
 
         return dist
-    end
+       end
+
+       private
+       def get_flat_serveraddr()
+        server = @server_addr
+        if server.nil? or server.empty? then
+            @log.error "Server addr is nil"
+            return nil
+               end
+               
+               server = server.delete ".:/@"
+               return server
+       end                                     
 
     public
        # install package
     # install all install dependency packages
     def install(pkg_name, os, trace, force)
 
 
     public
        # install package
     # 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
 
         if trace.nil? then trace = true end
         if force.nil? then force = false end
 
@@ -501,43 +540,44 @@ class Client
             @log.error "#{pkg_name} package does not exist in remote package list"
             return false
         end
             @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
 
         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, 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)
+               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"
 
         if trace then
             @log.info "Installed \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK"
@@ -545,12 +585,22 @@ class Client
         else
             @log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
         end
         else
             @log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
         end
+
         return true
        end
 
         return true
        end
 
+
     public
     # install local package (ignore dependent packages)
     public
     # install local package (ignore dependent packages)
-    def install_local_pkg(pkg_path, force)
+    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]
 
         file_name = File.basename(pkg_path)
         pkg_name = file_name.split('_')[0]
@@ -566,50 +616,93 @@ class Client
             return false
         end
         pkg_name = filename.split("_")[0]
             return false
         end
         pkg_name = filename.split("_")[0]
-        type = "binary"
         manifest_file = "pkginfo.manifest"
         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}"
 
         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
+               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
             end
-        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 { |repos_path|
+                                               binpkgs += Dir.glob("#{repos_path}/#{p.package_name}_*_#{new_pkg_os}.zip")
+                                       }
+                                       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
 
 
-        if check_installed_pkg(pkg_name) then
-            uninstall(pkg_name, false)
-        end
+               # install package
+               ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location, @log)
 
 
-        # install package
-        ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location)
+               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)
+               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
 
 
         @log.info "Installed \"#{pkg_path} [#{new_pkg_ver}]\" file.. OK"
         return true
     end
 
+
     public
     # upgrade package
     def upgrade(os, trace)
     public
     # upgrade package
     def upgrade(os, trace)
@@ -630,7 +723,7 @@ class Client
                 end
             end
 
                 end
             end
 
-            if not install(p, os, trace, false) then
+            if not install_internal(p, os, trace, false) then
                 @log.error "Failed to install \"#{p}\" package.."
                 return false
             end
                 @log.error "Failed to install \"#{p}\" package.."
                 return false
             end
@@ -753,7 +846,7 @@ class Client
 
         pkg_list.each do |p|
             if not check_installed_pkg(p) then next end
 
         pkg_list.each do |p|
             if not check_installed_pkg(p) then next end
-            if not FileInstaller.uninstall(p, type, @location) then
+            if not FileInstaller.uninstall(p, type, @location, @log) then
                 @log.error "Failed uninstall \"#{pkg_name}\" package"
                 return false
             end
                 @log.error "Failed uninstall \"#{pkg_name}\" package"
                 return false
             end
@@ -784,11 +877,11 @@ class Client
                 return
             end
         end
                 return
             end
         end
-        FileUtils.rm_rf(@location)
+               if File.exist? @location then FileUtils.rm_rf(@location) end
         FileUtils.mkdir_p(@location)
         FileUtils.mkdir_p(@location)
-        @pkg_hash_os.clear
+        #@pkg_hash_os.clear
         @installed_pkg_hash_loc.clear
         @installed_pkg_hash_loc.clear
-        @archive_pkg_list.clear
+        #@archive_pkg_list.clear
         @log.info "Cleaned \"#{@location}\" path.. OK"
     end
 
         @log.info "Cleaned \"#{@location}\" path.. OK"
     end
 
@@ -798,13 +891,14 @@ class Client
 
         result = []
         pkg_hash = @pkg_hash_os[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
         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)
+                    result.push(pkg)
                 end
             end
         end
                 end
             end
         end
@@ -814,18 +908,20 @@ class Client
 
     public
        # get reverse source dependent packages (just 1 depth)
 
     public
        # get reverse source dependent packages (just 1 depth)
-    def get_reverse_source_dependent_packages(pkg_name, os)
+    def get_reverse_source_dependent_packages(pkg_name)
 
         result = []
 
         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
+        @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
 
         return result
     end
@@ -938,7 +1034,7 @@ class Client
             i = i + 1
         end
         
             i = i + 1
         end
         
-        @log.info "Get install dependent packages for #{pkg_name} package.. OK"
+        @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
         if reverse then return result.reverse.uniq.push(pkg_name)
         else return result.uniq.insert(0, pkg_name) end
     end
@@ -998,7 +1094,7 @@ class Client
         if pkg_hash.nil? then return false end
         pkg = pkg_hash[pkg_name]
         if pkg.nil? then
         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"
+            #@log.warn "There is no \"#{pkg_name}\" remote package information in list"
             return false
         end
 
             return false
         end
 
@@ -1048,6 +1144,7 @@ class Client
         if pkg.nil? then return nil end
 
         case attr
         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 "path" then return pkg.path
         when "source" then return pkg.source
         when "version" then return pkg.version
@@ -1056,6 +1153,9 @@ class Client
         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 "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
 
         end
     end
 
@@ -1209,11 +1309,12 @@ class Client
         return s
     end
 
         return s
     end
 
-    private 
+    public
     def get_pkg_from_list(pkg_name, os)
 
         pkg_hash = @pkg_hash_os[os]
         if pkg_hash.nil? then return nil end
     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
         pkg = pkg_hash[pkg_name]
         
         return pkg
@@ -1246,16 +1347,20 @@ class Client
         # below code should be changed
         type = path.split('/')[-2]
         new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
         # 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
             
         # 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"
+               @log.warn "Checked \"#{pkg_name}\" package version : it is bigger then remote package version"
                return true
             when 0 then
                return true
             when 0 then
-               @log.warn "\"#{pkg_name}\" package version is same with remote package version"
+               @log.warn "Checked \"#{pkg_name}\" package version : it is same with remote package version"
                return true
             end
         end
                return true
             end
         end
@@ -1268,32 +1373,34 @@ class Client
             end
         end 
 
             end
         end 
 
-        # download package 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 
-            FileUtils.remove_dir(tmppath, true)
-            return false 
-        end
-    
         # install package
         # install package
-        ret = FileInstaller.install(pkg_name, file_local_path, type, @location)
-        FileUtils.rm_f(file_local_path)
-        FileUtils.remove_dir(tmppath, true)
+               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
         return ret
-    end
+       end
 
     private
 
     private
-    def compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+       def compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
 
         if check_installed_pkg_list_file() then
 
         if check_installed_pkg_list_file() then
-            create_installed_pkg_hash()
+            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)
             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)
@@ -1332,14 +1439,14 @@ class Client
         else pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) end
         @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
 
         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"
+        #@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)
         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)
 
         config_path = File.join(@location, PACKAGE_INFO_DIR, "#{pkg_name}")
         pkg = read_pkginfo_file(pkg_name, config_path)
 
@@ -1356,7 +1463,7 @@ class Client
         else pkg_hash[pkg_name] = pkg end
         @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
 
         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"
+        #@log.info "Added information for \"#{pkg_name}\" package.. OK"
         return pkg_hash
     end
 
         return pkg_hash
     end
 
@@ -1365,75 +1472,203 @@ class Client
     def read_pkginfo_file(pkg_name, path)
 
         file_path = File.join(path, "pkginfo.manifest")
     def read_pkginfo_file(pkg_name, path)
 
         file_path = File.join(path, "pkginfo.manifest")
-        pkg_hash = Parser.read_pkg_list(file_path)
+               begin
+                       pkg = Parser.read_single_pkginfo_from file_path
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       return nil
+               end
 
 
-        if pkg_hash.nil? then
+        if pkg.nil? then
             @log.error "Failed to read manifest file : #{file_path}"
             return nil
         end
 
             @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]
+        @log.info "Read information for \"#{pkg_name}\" package.. OK"
+        return pkg
     end
 
     end
 
-    private
+    # get the lastest snapshot 
     # from_server : if true, update from server
     # 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
+       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
+       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
+       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
-        local_file_path = File.join(CONFIG_PATH, filename)
+       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|
         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)
+                                       pkg = l.strip                                           
+                                       if @archive_pkg_list.index(pkg).nil? then @archive_pkg_list.push(pkg) end
                 end
                 end
-            end
+                       end
+                       @log.info "Get archive package infomation.. OK"
+               else                    
+                       @log.warn "Failed to get archive package infomation"
         end
         end
+       end
 
 
-        return true
-    end
-    
-    private
-    # create installed package hash
-    def create_installed_pkg_hash()
+       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
 
         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      
+        else
             file_path = installed_pkg_hash_key
             if not File.exist? file_path then
                 #raise RuntimeError, "#{file_path} file does not exist"
                 return
             end
             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
+                       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
 
     private
     # check to exist installed package list file
@@ -1463,11 +1698,9 @@ class Client
         end
         if not pkg_hash.nil? then
             config_path = File.join(@location, PACKAGE_INFO_DIR)
         end
         if not pkg_hash.nil? then
             config_path = File.join(@location, PACKAGE_INFO_DIR)
-            FileUtils.mkdir_p "#{config_path}"
+            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|
             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)
                 pkg_list = pkg_hash.values
                 pkg_list.each do |pkg|
                     pkg.print_to_file(file)
index ae12c36055a3e9c56170922750a2cde0a9fa1708..695bd43b609952e5ff0165747896d6c593a8ee08 100644 (file)
@@ -36,8 +36,7 @@ def set_default( options )
        if options[:v].nil? then options[:v] = false end
 end
 
        if options[:v].nil? then options[:v] = false end
 end
 
-def option_error_check( options )
-       $log.info "option error check"
+def option_error_check( options )      
 
        case options[:cmd]
 
 
        case options[:cmd]
 
@@ -51,167 +50,151 @@ def option_error_check( options )
 
     when "download" then
         if options[:pkg].nil? or options[:pkg].empty? then 
 
     when "download" then
         if options[:pkg].nil? or options[:pkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli download -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>] [-t]"
-        end
-
-    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 <ssh_alias> -i <id> -s <source_package_path_list> [-b <binary_package_path_list>]"
-        end
-
-    when "source" then
-        if options[:pkg].nil? or options[:pkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli source -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>]"
+                   raise ArgumentError, "Usage: pkg-cli download -P <package name> [-o <os>] [-l <location>] [-u <package server url>] [--trace]"
         end
 
     when "install" then
         if options[:pkg].nil? or options[:pkg].empty? then 
         end
 
     when "install" then
         if options[:pkg].nil? or options[:pkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli install -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>] [-t] [-f]"
+                   raise ArgumentError, "Usage: pkg-cli install -P <package name> [-o <os>] [-l <location>] [-u <package server url>] [--trace] [--force]"
         end
 
     when "install-file" then
         if options[:pkg].nil? or options[:pkg].empty? then 
         end
 
     when "install-file" then
         if options[:pkg].nil? or options[:pkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli install-lpkg -p <pkg_file> [-l <location>] [-f]"
+                   raise ArgumentError, "Usage: pkg-cli install-lpkg -P <package file> [-l <location>] [-u <package server url>] [--trace] [--force]"
         end
 
     when "uninstall" then
         if options[:pkg].nil? or options[:pkg].empty? then 
         end
 
     when "uninstall" then
         if options[:pkg].nil? or options[:pkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli uninstall -p <pkg_name> [-l <location>] [-t]"
+                   raise ArgumentError, "Usage: pkg-cli uninstall -P <package name> [-l <location>] [--trace]"
         end
 
     when "show-rpkg" then
         if options[:pkg].nil? or options[:pkg].empty? then
         end
 
     when "show-rpkg" then
         if options[:pkg].nil? or options[:pkg].empty? then
-                   raise ArgumentError, "Usage: pkg-cli show-rpkg -p <pkg_name> [-o <os>] [-u <package server url>]"
+                   raise ArgumentError, "Usage: pkg-cli show-rpkg -P <package name> [-o <os>] [-u <package server url>]"
         end
 
     when "list-rpkg" then
 
     when "show-lpkg" then
         if options[:pkg].nil? or options[:pkg].empty? then
         end
 
     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 <pkg_name> [-l <location>]"
+                   raise ArgumentError, "Usage: pkg-cli show-lpkg -P <package name> [-l <location>]"
         end
 
     when "list-lpkg" then
 
     when "build-dep" then
         if options[:pkg].nil? or options[:pkg].empty? then
         end
 
     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 <pkg_name> [-o <os>]"
+                   raise ArgumentError, "Usage: pkg-cli build-dep -P <package name> [-o <os>]"
         end
 
     when "install-dep" then
         if options[:pkg].nil? or options[:pkg].empty? then
         end
 
     when "install-dep" then
         if options[:pkg].nil? or options[:pkg].empty? then
-                   raise ArgumentError, "Usage: pkg-cli install-dep -p <pkg_name> [-o <os>]"
+                   raise ArgumentError, "Usage: pkg-cli install-dep -P <package name> [-o <os>]"
         end
 
        else
         end
 
        else
-               raise ArgumentError, "input option incorrect : #{options[:cmd]}"
+               raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
        end
 end
 
 def option_parse 
     options = {}
        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 <remote_server_url>]" + "\n" \
-        + "\t" + "pkg-cli clean [-l <location>] [-f]" + "\n" \
-        + "\t" + "pkg-cli download -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>] [-t]" + "\n" \
-        + "\t" + "pkg-cli upload -a <ssh_alias> -i <id> -s <source_package_path_list> [-b <binary_package_path_list]" + "\n" \
-        + "\t" + "pkg-cli source -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>]" + "\n" \
-        + "\t" + "pkg-cli install -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>] [-t] [-f]" + "\n" \
-        + "\t" + "pkg-cli install-file -p <pkg_file> [-l <location>] [-f]" + "\n" \
-        + "\t" + "pkg-cli uninstall -p <pkg_name> [-l <location>] [-t]" + "\n" \
-        + "\t" + "pkg-cli upgrade [-l <location>] [-o <os>] [-u <package server url>] [-t]" + "\n" \
+    banner = "Requiest service to package-server and control packages service command-line tool." + "\n" \
+        + "\n" + "Usage: pkg-cli <SUBCOMMAND> [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 <remote server url>]" + "\n" \
+        + "\t" + "pkg-cli clean [-l <location>] [--force]" + "\n" \
+        + "\t" + "pkg-cli download -P <package name> [-o <os>] [-l <location>] [-u <package server url>] [--trace]" + "\n" \
+        + "\t" + "pkg-cli install -P <package name> [-o <os>] [-l <location>] [-u <package server url>] [--trace] [--force]" + "\n" \
+        + "\t" + "pkg-cli install-file -P <package file> [-l <location>] [-u <package server url>] [--trace] [--force]" + "\n" \
+        + "\t" + "pkg-cli uninstall -P <package name> [-l <location>] [--trace]" + "\n" \
+        + "\t" + "pkg-cli upgrade [-l <location>] [-o <os>] [-u <package server url>] [--trace]" + "\n" \
         + "\t" + "pkg-cli check-upgrade [-l <location>] [-o <os>] [-u <package server url>]" + "\n" \
         + "\t" + "pkg-cli check-upgrade [-l <location>] [-o <os>] [-u <package server url>]" + "\n" \
-        + "\t" + "pkg-cli show-rpkg -p <pkg_name> [-o <os>] [-u <package server url>]" + "\n"  \
+        + "\t" + "pkg-cli show-rpkg -P <package name> [-o <os>] [-u <package server url>]" + "\n"  \
         + "\t" + "pkg-cli list-rpkg [-o <os>] [-u <package server url>]" + "\n" \
         + "\t" + "pkg-cli list-rpkg [-o <os>] [-u <package server url>]" + "\n" \
-        + "\t" + "pkg-cli show-lpkg -p <pkg_name> [-l <location>]" + "\n"  \
+        + "\t" + "pkg-cli show-lpkg -P <package name> [-l <location>]" + "\n"  \
         + "\t" + "pkg-cli list-lpkg [-l <location>]" + "\n" \
         + "\t" + "pkg-cli list-lpkg [-l <location>]" + "\n" \
-        + "\t" + "pkg-cli build-dep -p <pkg_name> [-o <os>]" + "\n"  \
-        + "\t" + "pkg-cli install-dep -p <pkg_name> [-o <os>]" + "\n"  \
+        + "\t" + "pkg-cli build-dep -P <package name> [-o <os>]" + "\n" \
+        + "\t" + "pkg-cli install-dep -P <package name> [-o <os>]" + "\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 <pkg_name or pkg_file>', 'package name or package file name' ) do |name|
+        opts.on( '-P', '--pkg <package name/file>', 'package name or package file name' ) do |name|
             options[:pkg] = name 
         end
         
             options[:pkg] = name 
         end
         
-               opts.on( '-o', '--os <operating system>', 'target operating system' ) do |os|
+           opts.on( '-o', '--os <operating system>', 'target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64' ) do |os|
             options[:os] = os
         end
                
             options[:os] = os
         end
                
-               opts.on( '-u', '--url <server_address>', 'package server url' ) do|url|
+           opts.on( '-u', '--url <server url>', 'package server url: http://127.0.0.1/dibs/unstable' ) do |url|
             options[:url] = url 
         end
 
             options[:url] = url 
         end
 
-               opts.on( '-a', '--alias <ssh_alias>', 'ssh alias' ) do|al|
-            options[:alias] = al
-        end
-
-               opts.on( '-i', '--id <id>', 'id' ) do|id|
-            options[:id] = id
-        end
-
-               opts.on( '-l', '--loc <location>', 'location' ) do |loc|
-            options[:loc] = loc
+       opts.on( '-l', '--loc <location>', 'install/download location' ) do |loc|
+            options[:loc] = loc            
         end
 
         end
 
-               opts.on( '-s', '--src <source_package>', '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
+           opts.on( '--trace', 'enable trace dependent packages' ) do
             options[:t] = true
         end
 
             options[:t] = true
         end
 
-               opts.on( '-b', '--bin <binary_package>', '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
+           opts.on( '--force', 'enable force' ) do
             options[:f] = true
         end
                
             options[:f] = true
         end
                
-               opts.on( '-h', '--help', 'display this information' ) do
+           opts.on( '-h', '--help', 'display help' ) do
             puts opts
             puts opts
+               exit
+        end
+
+               opts.on( '-v', '--version', 'display version' ) do
+            puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
                        exit
         end
                        exit
         end
-               
     end
     end
-    
-       $log.info "option parsing start" 
-    $log.info "option is : " + ARGV * "," 
 
     cmd = ARGV[0] 
 
     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 \
+    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
             cmd =~ /(help)|(-h)|(--help)/  then
-        if cmd.eql? "help" then ARGV[0] = "-h" end
+
+        if cmd.eql? "help" then 
+            V[0] = "-h" 
+        end
         options[:cmd] = ARGV[0]
     else
         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]}"
+        raise ArgumentError, "Usage: pkg-cli <SUBCOMMAND> [OPTS] or pkg-cli -h"
     end
 
     optparse.parse!
     end
 
     optparse.parse!
-   
-       $log.info "option parsing end" 
 
        set_default options
 
 
        set_default options
 
index 535f99e729f2a5dc80227a35107dab0ef0d22275..d386890f3b1633401603d52242fa6d604f1fcf04 100644 (file)
@@ -29,14 +29,17 @@ Contributors:
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "parser"
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "parser"
+require "installer"
 
 class Distribution 
 
 class Distribution 
-       attr_accessor :name, :location, :server_url
+       attr_accessor :name, :location, :server_url, :lock_file_path
 
     # constant
 
     # constant
-    SUPPORTED_OS = ["linux", "windows", "darwin"]
     PKG_LIST_FILE_PREFIX = "pkg_list_" 
     PKG_LIST_FILE_PREFIX = "pkg_list_" 
-       ARCHIVE_PKG_LIST = "archive_pkg_list"
+       ARCHIVE_PKG_FILE = "archive_pkg_list"
+       OS_INFO_FILE = "os_info"
+       SNAPSHOT_INFO_FILE = "snapshot.info"
+       LOCK_FILE = ".lock_file"
 
        def initialize( name, location, server_url, pkg_server )
 
 
        def initialize( name, location, server_url, pkg_server )
 
@@ -45,31 +48,32 @@ class Distribution
                @server_url = server_url
                @log = pkg_server.log
                @integrity = pkg_server.integrity 
                @server_url = server_url
                @log = pkg_server.log
                @integrity = pkg_server.integrity 
+               @lock_file_path = "#{location}/#{LOCK_FILE}"
+               @pkg_hash_os = {}  
+               @archive_pkg_list = [] 
+               @snapshot_hash = [] 
+               @support_os_list = []
 
                @log.info "Distribution class[#{name}] initialize "
 
 
                @log.info "Distribution class[#{name}] initialize "
 
-               @pkg_hash_os = {}  
-        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
 
        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 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?
                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 not ( 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
 
                        end
                end
 
@@ -77,11 +81,16 @@ class Distribution
                pkg.origin = "local" 
         pkg.source = ""
                pkg.path = "/binary/" + File.basename( file_path )
                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 
                
@@ -89,7 +98,6 @@ class Distribution
        end
 
        def register_for_test (file_path, 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
                if pkg.nil? then
                        raise RuntimeError, "package file does not contain pkginfo.manifest: [#{file_path}]"
                end
@@ -99,7 +107,7 @@ class Distribution
         pkg.source = ""
                pkg.path = "/temp/" + File.basename( file_path )
                # TODO: windows and mac : sha256sum
         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
                        pkg.checksum = `sha256sum #{file_path}`.split(" ")[0]
                end
                pkg.size = `du -b #{file_path}`.split[0].strip
@@ -107,8 +115,15 @@ class Distribution
                return pkg
        end
 
                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)
                # if name is nil or empty then create uniq name
                if name.nil? or name.empty? then
                        name = Utils.create_uniq_name
                # if name is nil or empty then create uniq name
                if name.nil? or name.empty? then
                        name = Utils.create_uniq_name
@@ -119,294 +134,372 @@ class Distribution
                        raise "Snapshot is already exist: #{name}"
                end
 
                        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}"
+               
+               # 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 
+               
+               # copy archive package list
+               FileUtils.copy_file( "#{snapshot_path}/#{ARCHIVE_PKG_FILE}", 
+                               "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_FILE}" )
+               
+               # copy os info file 
+               FileUtils.copy_file( "#{snapshot_path}/#{OS_INFO_FILE}", 
+                               "#{@location}/snapshots/#{name}/#{OS_INFO_FILE}" )
 
 
-               for os in SUPPORTED_OS 
-                               FileUtils.copy( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", 
-                                                          "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{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 
+               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"  
+               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
                        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  
 
 
+       def sync(force) 
+               pkg_list_update_flag = false
+               archive_update_flag = false
+               distribution_update_flag = false
 
 
-                       @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 )
+               # reload pkg list from newest pkg list file
+               reload_distribution_information()
+
+               # check distribution's server_url
+               if @server_url.empty? then 
+                       @log.error("This distribution has not remote server", Log::LV_USER)
+                       return false
+               end
+
+               # generate client class
+               client = Client.new( @server_url, "#{@location}/binary", @log )
+
+               # update os list
+               add_os_list = client.support_os_list - @support_os_list
+               add_os_list.each do |os|
+                       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)
+                               pkg_list_update_flag = true
                        end
                        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
+               update_pkg_list = []
+
+               @support_os_list.each do |os|
+                       # error check 
+                       if client.pkg_hash_os[os].nil? then 
+                               @log.error("package server does not have os : #{os}", Log::LV_USER)
+                               next
+                       end 
+
+                       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.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
+               end
+               
+               # sync archive package 
+               update_archive_list = sync_archive_pkg()
 
 
-                       @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER)
-               # base_snapshot is empty
-               else 
-                       FileUtils.mkdir "#{@location}/snapshots/#{name}" 
+               # lock
+               lock_file = Utils.file_lock(@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"  
+               # 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
 
                        end
 
-                       @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER)
-               end
-       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
 
 
-       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
+                                       # if package is update when sync time then skip
+                                       if Utils.compare_version(local_pkg.version, pkg.version) == -1 then
+                                               next
+                                       end
+                               end
+                                       
+                               @pkg_hash_os[os][pkg.package_name] = pkg
+                       when "REMOVE" 
+                               if not force then
+                                       if @pkg_hash_os[os][pkg.package_name].origin.eql? "local" then 
+                                               next
+                                       end
+                               end
+
+                               @pkg_hash_os[os].delete(pkg.package_name)
+                       else
+                               @log.error("Unsupportd update option : #{update_option}", Log::LV_USER)
+                               next
+                       end
                end
                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_archive_list.each do |pkg|
+                       if not @archive_pkg_list.include? pkg then
+                               @archive_pkg_list.push pkg
+                               archive_update_flag = true
                        end
                        end
-               end     
-       end
+               end
 
 
-       def sync( force, os ) 
+               # update pkg_list file
+               if pkg_list_update_flag then
+                       write_all_pkg_list()
+                       distribution_update_flag = true
+               end
 
 
-               # check distribution's server_url
-               if @server_url.empty? then 
-                       @log.error( "This distribution has not remote server"  , Log::LV_USER)
-                       return
+               # update archive list file
+               if archive_update_flag then
+               write_archive_pkg_list()
+                       distribution_update_flag = true
                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 
+               # unlock 
+               Utils.file_unlock(lock_file)
 
 
-               # 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 
+               return distribution_update_flag
+       end
 
 
-               full_pkg_list = client_bin.pkg_hash_os[os].merge(@pkg_hash_os[os])
+       def add_os(os)
+               if @support_os_list.include? os then
+                       @log.error("#{os} is already exist ", Log::LV_USER)
+                       return 
+               end
 
 
-               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] 
+               # 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
 
 
-                       # 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 ( Utils.compare_version( local_pkg.version, server_pkg.version ).eql? 0 ) then 
-                                       @log.info "existing packages version equal to server's version. so package[#{pkg_name}] skip"
-                                       
-                                       next
-                               end 
+               # create pkg_list_#{os} file 
+               File.open( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f| end
+       end
 
 
-                               # 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 
+       def clean( remain_snapshot_list )
+               file_list = []
+               used_archive_list = []
 
 
-                               # 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}]"
+               # collect remaining file's name from current package server version
+        @support_os_list.each do |os|
+                       @pkg_hash_os[os].each_value{ |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
                                        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.error("Can't find dependency source package : #{source_dep.package_name}")
                                        end
                                end
                                        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)
+                       }
+               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
                                end
+                       # if snapshot does not have os_info file then using package server os_info list
                        else
                        else
-                               raise RuntimeError,"hash merge error!"
+                               os_list = @support_os_list
                        end
                        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 
+                       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{ |pkg|
+                                               file_list.push(pkg.path.sub("/binary/",""))
+                                       }
+                               rescue => e
+                                       @log.error( e.message, Log::LV_USER)
+                               end
+                       end
+
+                       used_archive_list = used_archive_list + read_archive_pkg_list( snapshot )
                end 
 
                end 
 
-               @log.info "pkg deb file update end"
-               # pakcage list file update
-               write_pkg_list(os)
-               @log.info "write pkg list"
-       end
+               file_list.uniq!
+               used_archive_list.uniq!
 
 
-       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
-                               end
+               # 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 
 
                        end
                end 
 
-               write_archive_pkg_list( downloaded_list )
-       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
+
+       def write_all_pkg_list
+               @support_os_list.each do |os|
+                       write_pkg_list(os)
+               end
+       end
 
        def write_pkg_list( os )
 
        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|
                        @pkg_hash_os[os].each_value do |pkg|
+                               # insert package information to file 
                                pkg.print_to_file(f)
                                pkg.print_to_file(f)
+                               # insert empty line to file 
                                f.puts 
                        end
                end     
                                f.puts 
                        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 
        def get_package_from_file(file_path)
        end
 
        # 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
                else
-                       raise "unsupported zipping file. just use [zip/tar.gz]"
+                       return nil
                end
                end
-               pkg = Parser.read_pkginfo( "#{@location}/#{tmp_dir}/pkginfo.manifest" )
-               FileUtils.rm_rf "#{@location}/#{tmp_dir}"
 
 
-               return pkg
+               # 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 )  
        end 
 
        def remove_pkg( pkg_name_list, os )  
-               for package_name in pkg_name_list
+               if os.eql? "all" then os_list = @support_os_list
+               else os_list = [ os ]
+               end
+
+               pkg_name_list.each do |package_name|
                        removed_flag = false 
 
                        removed_flag = false 
 
-                       if os.eql? "all" then os_list = SUPPORTED_OS
-                       else os_list = [ os ]
-                       end
+               os_list.each do |os|
+                               if not @support_os_list.include? os then
+                                       @log.error( "package server does not support input os : #{os}")
+                                       next
+                               end
 
 
-               for os in os_list
                                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)  
                                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)  
@@ -415,73 +508,403 @@ class Distribution
                        end  
 
                        if not removed_flag then 
                        end  
 
                        if not removed_flag then 
-                               @log.error( "Can't find package: #{package_name}", Log::LV_USER)
+                               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
                end 
-
+               
                # check install dependency integrity
                # check install dependency integrity
-               check_integrity 
+               if @integrity.eql? "YES" then
+                       @log.info "integrity check"
+                       check_integrity 
+               else
+                       @log.info "skip integrity check"
+               end 
 
 
-        for os in SUPPORTED_OS 
+
+               # update pkg_list file
+               os_list.each do |os|
                        write_pkg_list(os) 
                end
                        write_pkg_list(os) 
                end
+               write_archive_pkg_list
        end 
 
        end 
 
+       def remove_snapshot( snapshot_list )
+               remain_snapshot = []
+               removed_snapshot = []
+
+               # remove unused snapshot 
+               Dir.new( @location + "/snapshots" ).each do |snapshot|
+                       if snapshot.start_with? "." then next end
+
+                       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" 
 
        def check_integrity 
                @log.info "check server pkg's install dependency integrity" 
 
-               if not @integrity.eql? "YES" then
-                       @log.info "skip integrity check"
-                       return 
+               @support_os_list.each do |os|
+                       @pkg_hash_os[os].each_value.each do |pkg|
+                               check_package_integrity(pkg)
+                       end
                end 
                end 
+       end
 
 
-               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 "  
+       def check_package_integrity(pkg)
+               error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s install dependency not matched in "  
+               os = pkg.os
 
 
-                               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
+               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 ( 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 
                                
                                
-                                       # check package's version 
-                                       if not dep.match? target_pkg.version then 
-                                               raise RuntimeError,(error_msg + dep.to_s)
-                                       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 
 
 
-                               end 
+               # generate temp file
+               tmp_file_name = ""
+               while ( tmp_file_name.empty? )
+                       tmp_file_name = @location + "/temp/." + Utils.create_uniq_name
 
 
-                               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 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 { |line|
+                               if line =~ /name :/ then 
+                                       if remain_snapshot_list.include? line.split(':')[1].strip then
+                                               save_flag = true
                                        else
                                        else
-                                               build_dep_os = dep.target_os_list[0]
+                                               save_flag = false
                                        end
 
                                        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}]'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
+
+                               if save_flag then 
+                                       f.puts line
+                               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{ |dpkg|
+                               if dpkg.install_dep_list.include? pkg or \
+                                               dpkg.build_dep_list.include? pkg then
+                                       depends_list.push opkg  
+                               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 
                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
        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
 end
index 03082080a04b118469abfbc71cdd08c64886d31b..7e5a8c885a626addaba5dc5806a0b1a6e9bb6cf5 100644 (file)
@@ -31,30 +31,25 @@ require "utils"
 
 class FileDownLoader
 
 
 class FileDownLoader
 
-    @@log = nil
-
-    def FileDownLoader.set_logger(logger)
-        @@log = logger
-    end
-
-    def FileDownLoader.download(url, path)
+    def FileDownLoader.download(url, path, logger)
         ret = false
 
         if not File.directory? path then
         ret = false
 
         if not File.directory? path then
-            @@log.error "\"#{path}\" does not exist"
+            logger.error "\"#{path}\" does not exist"
             return ret
             return ret
-        end
-        
+               end
+
         is_remote = Utils.is_url_remote(url)
         filename = url.split('/')[-1]
         is_remote = Utils.is_url_remote(url)
         filename = url.split('/')[-1]
-
         fullpath = File.join(path, filename)
 
         fullpath = File.join(path, filename)
 
+               logger.info "Downloading #{url}"
         if is_remote then
         if is_remote then
-            ret = system "wget #{url} -O #{fullpath} -nv"
+            ret = Utils.execute_shell_with_log( "wget #{url} -O #{fullpath} -nv", logger )
+            #ret = Utils.execute_shell( "wget #{url} -O #{fullpath} -q")
         else
             if not File.exist? url then
         else
             if not File.exist? url then
-                @@log.error "\"#{url}\" file does not exist"
+                logger.error "\"#{url}\" file does not exist"
                 return false
             else
                 ret = system "cp #{url} #{fullpath}"
                 return false
             else
                 ret = system "cp #{url} #{fullpath}"
@@ -62,6 +57,12 @@ class FileDownLoader
         end
 
         # need verify
         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
         return ret
     end
 end
index 84ea930cfee68db5d0f6850c381eb5df8500800c..d9582b88fbda01d03c0ea1b3b9a6d4470aeb5488 100644 (file)
@@ -31,22 +31,21 @@ $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "packageServerConfig"
 require "log"
 require "utils"
 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 = "#{PackageServerConfig::CONFIG_ROOT}/client"
     PACKAGE_INFO_DIR = ".info"
 
 class FileInstaller
 
     CONFIG_PATH = "#{PackageServerConfig::CONFIG_ROOT}/client"
     PACKAGE_INFO_DIR = ".info"
+       PACKAGE_MANIFEST = "pkginfo.manifest"
 
 
-    @@log = nil
-
-    def FileInstaller.set_logger(logger)
-        @@log = logger
-    end
-
-    def FileInstaller.install(package_name, package_file_path, type, target_path)
+    def FileInstaller.install(package_name, package_file_path, type, target_path, logger)
 
         if not File.exist? package_file_path then
 
         if not File.exist? package_file_path then
-            @@log.error "\"#{package_file_path}\" file does not exist."
+            logger.error "\"#{package_file_path}\" file does not exist."
             return false
         end
 
             return false
         end
 
@@ -55,81 +54,153 @@ class FileInstaller
         when "binary" then
             uniq_name = Utils.create_uniq_name
             path = Utils::HOME + "/tmp/#{uniq_name}"
         when "binary" then
             uniq_name = Utils.create_uniq_name
             path = Utils::HOME + "/tmp/#{uniq_name}"
-            if Utils::HOST_OS.eql? "windows" then
+            # 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
                 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 
+            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
             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}")
-
+                       write_log(target_path, package_name, log)
+=begin
             target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
             target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-            FileUtils.mkdir_p(target_config_path)
+            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
             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
         when "source" then
         end
 
         # need verify
+               logger.info "Installed \"#{package_name}\" package.. OK"
+               logger.info "  [path: #{target_path}]"
         return true;
         return true;
-    end
+       end
 
 
-    def FileInstaller.move_remove_script(package_name, path, target_path)
+       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}"
         target_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-        FileUtils.mkdir_p(target_path)
+        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]
         script_file_prefix = "#{path}/remove.*"
         script_file = Dir.glob(script_file_prefix)[0]
+               log = ""
 
         if not script_file.nil? then
 
         if not script_file.nil? then
-            FileUtils.mv(script_file, target_path)
-        end
+                       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 
 
 
     end 
 
 
-    def FileInstaller.execute_install_script(package_name, path, target_path)
+       # 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
         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"
-            if Utils::HOST_OS.eql? "windows" then
-                cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
+            logger.info "Execute \"#{script_file}\" file"
+            if Utils.is_windows_like_os( Utils::HOST_OS ) then
+                cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"        
             else
                 cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}"
             else
                 cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}"
-            end
+                       end
+                       logger.info "  [cmd: #{cmd}]"
             log = `#{cmd}`
             log = `#{cmd}`
-        end
+                       logger.info "Executed install script file.. OK"
+                       log = log + "[file: #{script_file}]\n"
+                       log = log + "[cmd: #{cmd}]\n"
+               end
+
         return log
     end
 
         return log
     end
 
-    def FileInstaller.execute_remove_script(package_name, target_path)
+       # 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
         info_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
         if not File.directory? info_path then
-            return false
+                       logger.error "\"#{info_path}\" does not exist."                 
+            return nil 
         end
 
         script_file_prefix = "#{info_path}/remove.*"
         end
 
         script_file_prefix = "#{info_path}/remove.*"
@@ -137,21 +208,28 @@ class FileInstaller
         log = ""
 
         if not script_file.nil? then
         log = ""
 
         if not script_file.nil? then
-            @@log.info "Execute \"#{script_file}\" file"
-            if Utils::HOST_OS.eql? "windows" then
+            logger.info "Execute \"#{script_file}\" file"
+            if Utils.is_windows_like_os( Utils::HOST_OS ) then
                 cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
             else
                 cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}"
             end
                 cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
             else
                 cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}"
             end
+                       logger.info "  [cmd: #{cmd}]"
             log = `#{cmd}`
             log = `#{cmd}`
-        end
+                       logger.info "Executed remote script file.. OK"
+                       log = log + "[file: #{script_file}]\n"
+                       log = log + "[cmd: #{cmd}]\n"
+               end
+
+               return log
     end
 
     end
 
-    def FileInstaller.remove_pkg_files(package_name, target_path)
+    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
         list_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
 
         if not File.directory? list_path then
-            return false
+                       logger.error "\"#{list_path}\" does not exist."                         
+            return false 
         end
 
         list_file_name = "#{list_path}/#{package_name}.list"
         end
 
         list_file_name = "#{list_path}/#{package_name}.list"
@@ -176,17 +254,18 @@ class FileInstaller
                             begin
                                 Dir.rmdir(file_path)
                             rescue SystemCallError
                             begin
                                 Dir.rmdir(file_path)
                             rescue SystemCallError
-                                @@log.warn "\"#{file_path}\" directory is not empty"
+                                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,
                             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
+                    else logger.warn "\"#{file_path}\" does not exist" end
                 end
             end
 
             directories.reverse.each do |path|
                 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
                 entries = Dir.entries(path)
                 if entries.include? "." then entries.delete(".") end
                 if entries.include? ".." then entries.delete("..") end
@@ -194,40 +273,67 @@ class FileInstaller
                 begin
                     Dir.rmdir(path)
                 rescue SystemCallError
                 begin
                     Dir.rmdir(path)
                 rescue SystemCallError
-                    @@log.warn "\"#{file_path}\" directory is not empty"
+                    logger.warn "\"#{file_path}\" directory is not empty"
                 end 
                 else next end
            end
         end
                 end 
                 else next end
            end
         end
-        #FileUtils.rm_rf(list_path)
         Utils.execute_shell("rm -rf #{list_path}")
         return true
     end
 
         Utils.execute_shell("rm -rf #{list_path}")
         return true
     end
 
-    def FileInstaller.uninstall(package_name, type, target_path)
+    def FileInstaller.uninstall(package_name, type, target_path, logger)
         case type
         when "binary" then
         case type
         when "binary" then
-            execute_remove_script(package_name, target_path)
-            remove_pkg_files(package_name, target_path)
+            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
 
         when "source" then
         end
 
         return true
     end
 
-    def FileInstaller.move_dir(package_name, source_path, target_path)
+    def FileInstaller.move_dir(package_name, source_path, target_path, logger)
         config_path = File.join(target_path, PACKAGE_INFO_DIR, package_name)
         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
+               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 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"
+               else logger.warn "\"data\" directory does not exist." end
+
+               return log
     end
 
     end
 
-    def FileInstaller.extract_file(package_name, package_file_path, path, target_path)
+    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}"
         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)
+        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"
         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"
@@ -235,16 +341,20 @@ class FileInstaller
 
         show_file_list_command = nil
         extrach_file_list_command = nil
 
         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}"
 
         case ext
         when ".zip" then
             show_file_list_command = "zip -sf #{package_file_path}"
-            extract_file_list_command = "unzip \"#{package_file_path}\" -d \"#{path}\""
+            extract_file_list_command = "unzip -o \"#{package_file_path}\" -d \"#{path}\""
         when ".tar" then
         when ".tar" then
-            show_file_list_command = "tar -sf #{package_file_path}"
-            extract_file_list_command = "tar xf \"#{package_file_path}\" -C \"#{path}\""
+            # 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
         else
-            @@log.error "\"#{filename}\" is not supported."
+            logger.error "\"#{filename}\" is not supported."
             return nil 
         end
 
             return nil 
         end
 
@@ -259,15 +369,44 @@ class FileInstaller
                 end
             end
         end
                 end
             end
         end
-
         File.delete(temp_pkg_file_list_path)
         File.delete(temp_pkg_file_list_path)
-        log = `#{extract_file_list_command}`
-        @@log.info "Extracted \"#{filename}\" file.. OK"
-        if log.nil? then log = "" end
+
+        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
 
         return log
     end
 
-    def FileInstaller.extract_specified_file(package_file_path, target_file, path)
+    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)
         dirname = File.dirname(package_file_path)
         filename = File.basename(package_file_path)
         ext = File.extname(filename)
@@ -280,11 +419,13 @@ class FileInstaller
                 extract_file_command = "unzip -x #{package_file_path} #{target_file}"
             end
         when ".tar" then
                 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
             if not path.nil? then
-                path = File.join(path, package_file_path)
-                extract_file_command = "tar xvf #{package_file_path} #{target_file}"
+                extract_file_command = "tar xf #{_package_file_path} -C #{_path} #{target_file}"
             else
             else
-                extract_file_command = "tar xvf #{package_file_path} #{target_file}"
+                extract_file_command = "tar xf #{_package_file_path} #{target_file}"
             end
         end
 
             end
         end
 
@@ -297,12 +438,46 @@ class FileInstaller
         end
 
         if File.exist? target_file_path then
         end
 
         if File.exist? target_file_path then
-            @@log.info "Extracted \"#{target_file}\" file.."
+            logger.info "Extracted \"#{target_file}\" file.."
             return true
         else
             return true
         else
-            @@log.info "Failed to extracted \"#{target_file}\" file.."
+            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
             return false
         end
     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
index 86abc39320247fbc86ae1963669dca09290b17cf..48dd649e5808f393b1fbd45958131709b3ba9804 100644 (file)
@@ -29,266 +29,250 @@ Contributors:
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 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 "packageServerConfig"
 require "distribution"
 require "packageServerLog"
 require "packageServerConfig"
 require "distribution"
+require "SocketRegisterListener"
 require "client"
 require "utils"
 require "mail"
 require "client"
 require "utils"
 require "mail"
+require "DistSync"
 
 class PackageServer
 
 class PackageServer
-       attr_accessor :id, :location, :log, :integrity
+       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"]
+    # constant
+       SERVER_ROOT = "#{PackageServerConfig::CONFIG_ROOT}/pkg_server"
+       DIBS_LOCK_FILE_PATH = "#{SERVER_ROOT}/.server_loc"
 
        # initialize
        def initialize (id)
 
        # initialize
        def initialize (id)
-               @id = id
                @location = ""
                @distribution_list = []
                # distribution name -> server_url hash
                @dist_to_server_url = {}
                @location = ""
                @distribution_list = []
                # distribution name -> server_url hash
                @dist_to_server_url = {}
-               @integrity = "NO"
-
-               if not File.exist?( PackageServerConfig::SERVER_ROOT )
-                       FileUtils.mkdir_p( PackageServerConfig::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
                end
-               @log = PackageServerLog.new( "#{PackageServerConfig::SERVER_ROOT}/.#{@id}.log" ) 
+               @log = PackageServerLog.new( @log_file_path )
 
                server_information_initialize()
        end
 
        # create
 
                server_information_initialize()
        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
                if loc.nil? or loc.empty? then
-                       @location = Dir.pwd + "/" + id 
+                       @location = Dir.pwd + "/" + @id 
                else
                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
 
                        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
                # create locking file
-               File.open("#{PackageServerConfig::LOCK_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? "#{PackageServerConfig::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 "#{PackageServerConfig::SERVER_ROOT}/#{id}"
-                       FileUtils.mkdir_p "#{PackageServerConfig::SERVER_ROOT}/#{id}/incoming"
+               lock_file = Utils.file_lock(DIBS_LOCK_FILE_PATH)
+
+               # 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))
+               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 
                                # 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 
+                       server_url = File.join(Utils::WORKING_DIR, server_url)
+               end 
 
 
-                       # create server configure file
-                       File.open( "#{PackageServerConfig::SERVER_ROOT}/#{id}/config", "w" ) do |f|
-                               f.puts "location : #{@location}"
-                               f.puts "integrity check : NO"
-                               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 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
 
 
                @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"
                @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 
                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(distribution.lock_file_path)
                
                
-                       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 
+               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 
 
 
-                               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     
+                       pkg = distribution.get_package_from_file(f) 
 
 
-                       # register binary package
-            binary_pkg_file_path_list.each do |l| 
-                               # get package class using bianry file 
-                               pkg = distribution.get_package_from_file(l) 
+                       # binary package
+                       if not pkg.nil? then
 
 
-                               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 )
+                               # 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
                                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
                                end
-                                       
-                               append_pkg_list.push pkg
-                       end 
 
 
-                       # check install dependency integrity
-                       if not test then distribution.check_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
                                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
-                       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)
+                               
+                               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 
 
 
-            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/" )
-                               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
+               end
 
 
-                       # write package list for updated os
-                       updated_os_list.uniq!
-                       updated_os_list.each do |os|
-               distribution.write_pkg_list( os ) 
+               # 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
+               end
 
 
-            # if snapshot mode is true then generate snapshot 
-            if snapshot or test then
-                               @log.info "generaging snapshot"
-                distribution.generate_snapshot("", "", "")
-                       end 
+        archive_pkg_file_path_list.each do |l|
+            FileUtils.mv( l, "#{distribution.location}/source/" )
+        end  
 
 
-                       # send email
-                       if not test then 
-                               msg_list = []
+               # write package list for updated os
+               updated_os_list.uniq!
+               updated_os_list.each do |os|
+               distribution.write_pkg_list(os) 
+               end
 
 
-                               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 )  
-                       end
-        }
+               # register archive pakcage list. 
+               distribution.write_archive_pkg_list()
+
+               # send email
+               if test_flag then 
+                       msg_list = []
+
+                       registed_package_list.each { |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 )  
+               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)
+               end 
+               
+               Utils.file_unlock(@lock_file)
                @log.output( "package registed successfully", Log::LV_USER)
                @log.output( "package registed successfully", Log::LV_USER)
+
+               return snapshot_name
     end
 
     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"
                @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 )
 
                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)
+               
+               Utils.file_unlock(@lock_file)
+               
+               return snapshot_name
        end
 
        def sync( dist_name, mode )
                @log.info "sync from server"
        end
 
        def sync( dist_name, mode )
                @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 
                distribution = get_distribution( dist_name ) 
        
                if distribution.server_url.empty? then 
@@ -296,67 +280,69 @@ class PackageServer
                        return
                end 
 
                        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
-               }
+               ret = distribution.sync(mode)
+               if ret then 
+                       distribution.generate_snapshot("", "", false)
+               end
                
                
-               @log.output( "package server [#{@id}]'s distribution [#{dist_name}] has the synchronization.", Log::LV_USER )
+               @log.output( "package server [#{@id}]'s distribution [#{dist_name}] has been synchronized.", Log::LV_USER )
        end
 
        def add_distribution( dist_name, server_url, clone )
        end
 
        def add_distribution( dist_name, server_url, clone )
-               File.open("#{PackageServerConfig::LOCK_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 
-
-                       File.open( "#{PackageServerConfig::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} ->  "
+               lock_file = Utils.file_lock(@server_lock_file_path)
+               
+               # 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
                                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
                                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
 
                @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)
+               
+               # distribution lock 
+               @lock_file = Utils.file_lock(dist.lock_file_path)
+               
+               dist.add_os(os)
+
+               @log.info "generaging snapshot"
+               dist.generate_snapshot("", "", false)
 
 
-               if File.exist? "#{PackageServerConfig::SERVER_ROOT}/#{id}/config" then
-                       File.open "#{PackageServerConfig::SERVER_ROOT}/#{id}/config" do |f|
+               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 
                                                location= l.split(" : ")[1]
                                f.each_line do |l|
                                        if l.start_with?( "location : ") then 
                                                location= l.split(" : ")[1]
@@ -366,78 +352,211 @@ class PackageServer
                                end
                        end
                else
                                end
                        end
                else
-                       @log.error( "Can't find server information : #{id}", Log::LV_USER)
+                       @log.error( "Can't find server information : #{@id}", Log::LV_USER)
                end 
                
                end 
                
-               FileUtils.rm_rf "#{PackageServerConfig::SERVER_ROOT}/.#{id}.log"
-               FileUtils.rm_rf "#{PackageServerConfig::SERVER_ROOT}/#{id}"
+               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_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 { |line|
+                               f.puts(line) if not line =~ /server_url : #{dist_name} ->/
+                       }
+               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 { |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
+
+               # remove distribution directory 
+               FileUtils.rm_rf distribution.location
                
                
-               @log.output( "package server [#{id}] removed successfully", Log::LV_USER )
+               # remove distribution struct
+               @distribution_list.delete distribution 
+
+               Utils.file_unlock(lock_file)
        end
 
        end
 
-       def remove_pkg( id, dist_name, pkg_name_list, os )
+       def remove_pkg( dist_name, pkg_name_list, os )
                @log.info "package remove in server"
                @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 = 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) 
-
-                       distribution.remove_pkg(pkg_name_list, os)
-               }
+               lock_file = Utils.file_lock(@server_lock_file_path)
+               
+               distribution.remove_pkg(pkg_name_list, os)
+       
+               # generate snapshot     
+               @log.info "generaging snapshot"
+               distribution.generate_snapshot("", "", false)
+
+               Utils.file_unlock(lock_file)
                @log.output( "package removed successfully", Log::LV_USER )
        end
                @log.output( "package removed successfully", Log::LV_USER )
        end
+       
+       def remove_snapshot( dist_name, snapshot_list )
+               @log.info "remove snapshot in server"
+               distribution = get_distribution( dist_name )
 
 
-       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
+               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 )
 
                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.output( "#{pkg}", Log::LV_USER)
+               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
                        else
-                               @log.error( "Can't find [#{pkg}] in source package", Log::LV_USER)
+                               sleep 1
                        end
                        end
-               end 
-       end
+               end
+       end 
+
+       # stop server daemon 
+       def stop( port, passwd )
+               # set port number. default port is 3333
+               @port = port 
+               @finish = false
+               
+               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 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)
+               end
+               client.terminate
+       
+       end 
 
        def self.list_id  
 
        def self.list_id  
-               @@log = PackageServerLog.new( "#{PackageServerConfig::SERVER_ROOT}/.log" 
+               @@log = PackageServerLog.new("#{SERVER_ROOT}/.log"
 
 
-               d = Dir.new( PackageServerConfig::SERVER_ROOT )
+               d = Dir.new( SERVER_ROOT )
                s = d.select {|f| not f.start_with?(".") }  
                s.sort!
                s = d.select {|f| not f.start_with?(".") }  
                s.sort!
+               server_list = []
        
                @@log.output( "=== server ID list ===", Log::LV_USER)
                s.each do |id|
        
                @@log.output( "=== server ID list ===", Log::LV_USER)
                s.each do |id|
+                       if File.extname(id).eql?(".log") then next end
+
+                       server_list.push id
                        @@log.output( id, Log::LV_USER)
                end 
                        @@log.output( id, Log::LV_USER)
                end 
+               @@log.close
+               FileUtils.rm_rf("#{SERVER_ROOT}/.log")
+
+               return server_list
        end
 
        def self.list_dist( id )
        end
 
        def self.list_dist( id )
-               @@log = PackageServerLog.new( "#{PackageServerConfig::SERVER_ROOT}/.log" ) 
+               @@log = PackageServerLog.new( "#{SERVER_ROOT}/.log" ) 
                
                @@log.output( "=== ID [#{id}]'s distribution list ===", Log::LV_USER)
 
                
                @@log.output( "=== ID [#{id}]'s distribution list ===", Log::LV_USER)
 
+               dist_list = []
+
                # read package id information
                # read package id information
-               if File.exist? "#{PackageServerConfig::SERVER_ROOT}/#{id}/config" then
-                       File.open "#{PackageServerConfig::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
-                               end
-                       end
-               else
+               config_file_path = "#{SERVER_ROOT}/#{id}/config"
+               if not File.exist? config_file_path
                        raise RuntimeError, "[#{id}] is not server ID"
                end 
                        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
+               end
+               @@log.close
+               FileUtils.rm_rf("#{SERVER_ROOT}/.log")
+
+               return dist_list
        end
 
        def get_default_dist_name() 
        end
 
        def get_default_dist_name() 
@@ -447,13 +566,28 @@ class PackageServer
                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 
 
        def server_information_initialize 
                # if id is nil or empty then find default id
                if @id.nil? or @id.empty? 
        # PRIVATE METHODS/VARIABLES
        private 
 
        def server_information_initialize 
                # if id is nil or empty then find default id
                if @id.nil? or @id.empty? 
-                       d = Dir.new( PackageServerConfig::SERVER_ROOT )
+                       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]}]"
                        s = d.select {|f| not f.start_with?(".") }
                        if s.length.eql? 1 then
                                @log.info "using default server ID [#{s[0]}]"
@@ -464,29 +598,40 @@ class PackageServer
                end
 
                # read package id information
                end
 
                # read package id information
-               if File.exist? PackageServerConfig::SERVER_ROOT and File.exist? "#{PackageServerConfig::SERVER_ROOT}/#{@id}/config" then
-                       File.open "#{PackageServerConfig::SERVER_ROOT}/#{@id}/config" do |f|
+               if File.exist? @config_file_path
+                       File.open @config_file_path do |f|
                                f.each_line do |l|
                                f.each_line do |l|
-                                       if l.start_with?( "location : ") then 
-                                               @location = l.split(" : ")[1].strip
-                                       elsif l.start_with?( "integrity check : ") then 
-                                               @integrity = l.split(" : ")[1].strip
-                                       elsif l.start_with?( "server_url : " ) then
-                                               info = l.split(" : ")[1].split("->")
+                                       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
                                                @dist_to_server_url[info[0].strip] = info[1].strip 
                                        else
                                                @log.error "server config file has invalid information [#{l}]"
                                        end
                                end
                        end
-               end
                
                
-               @dist_to_server_url.each do |dist_name, server_url|
-                       @distribution_list.push Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, self )
+                       @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 )
                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 
                @distribution_list.each do |dist|
                        if dist.name.eql? dist_name.strip
                                return dist 
@@ -497,12 +642,19 @@ class PackageServer
        end
 
        def create_distribution_struct( dist_name, server_url )
        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"
                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, self )
 
                # generate distribution
                distribution = Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, self )
 
@@ -517,20 +669,64 @@ class PackageServer
                        else 
                                @log.info "[#{dist_name}] distribution creation. using local server [#{server_url}]"
                        end
                        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)
                else
                        @log.info "generate package server do not using remote package server"
        
                        # write_pkg_list for empty file
                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
        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
index 7e19000ca07c904cd63b223c28389213320fdf5c..b2b447a92063696a1ce9dcc07277ee82d218bb55 100644 (file)
@@ -31,6 +31,4 @@ require "utils"
 
 class PackageServerConfig
        CONFIG_ROOT = "#{Utils::HOME}/.build_tools"
 
 class PackageServerConfig
        CONFIG_ROOT = "#{Utils::HOME}/.build_tools"
-       SERVER_ROOT = "#{PackageServerConfig::CONFIG_ROOT}/pkg_server"
-       LOCK_FILE = "#{PackageServerConfig::SERVER_ROOT}/.server_loc"
 end
 end
index da06a21cf356fd39b61615b579595a38a89d1766..fed7ace2c35f0e16d5a831c0868e7a21898ee18f 100644 (file)
@@ -31,19 +31,21 @@ $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "utils"
 
 def set_default( options ) 
 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
+       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 )
 end
 
 def option_error_check( options )
@@ -51,57 +53,99 @@ def option_error_check( options )
        case options[:cmd] 
        when "create" 
            if  options[:id].empty? or options[:dist].empty? then
        case options[:cmd] 
        when "create" 
            if  options[:id].empty? or options[:dist].empty? then
-                       raise ArgumentError, "Usage: pkg-svr create -i <id> -d <distribution> [-u <remote_server_url>] [-l <location>] "
-               end
-       when "remove-pkg"
-               if      options[:bpkgs].empty? then
-               raise ArgumentError, "pkg-svr remove-pkg -i <id> -d <distribution> -p <binary_package_name_list> [-o <os>]" + "\n" \
-               end
-       when "spkg-path"
-               if      options[:spkgs].empty? then
-               raise ArgumentError, "Usage: pkg-svr spkg-name -i <id> -d <distribution> -s <source_package_file_path> "
+                       raise ArgumentError, "Usage: pkg-svr create -n <server name> -d <distribution> [-u <remote server url>] [-l <location>] "
                end
        when "remove"
                if      options[:id].empty? then
                end
        when "remove"
                if      options[:id].empty? then
-               raise ArgumentError, "Usage: pkg-svr remove -i <id> "
+               raise ArgumentError, "Usage: pkg-svr remove -n <server name> "
+               end
+       when "remove-pkg"
+               if      options[:pkgs].empty? then
+               raise ArgumentError, "Usage: pkg-svr remove-pkg -n <server name> -d <distribution> -P <package file list> [-o <os>]" + "\n" \
+               end
+       when "remove-snapshot"
+               if      options[:snaps].empty? then
+               raise ArgumentError, "Usage: pkg-svr remove-snapshot -n <server name> -d <distribution> -s <snapshot list>"
                end
        when "add-dist"
            if  options[:id].empty? or options[:dist].empty? then
                end
        when "add-dist"
            if  options[:id].empty? or options[:dist].empty? then
-                       raise ArgumentError, "Usage: pkg-svr add-dist -i <id> -d <distribution> [-u <remote_server_url>] [-c] "
+                       raise ArgumentError, "Usage: pkg-svr add-dist -n <server name> -d <distribution> [-u <remote server url>] [--clone] "
+               end
+       when "add-os"
+           if options[:os].empty?  then
+                       raise ArgumentError, "Usage: pkg-svr add-os -n <server name> -d <distribution> -o <os>] "
+               end
+       when "remove-dist"
+           if  options[:id].empty? or options[:dist].empty? then
+                       raise ArgumentError, "Usage: pkg-svr remove-dist -n <server name> -d <distribution> "
                end
        when "register"
                end
        when "register"
-           if  options[:bpkgs].empty? and options[:spkgs].empty? then
-                       raise ArgumentError, "Usage: pkg-svr register -i <id> -d <distribution> -p <binary_package_file_path_list> -s <source_package_file_path_list> [-g] [-t] "
+           if  options[:pkgs].empty? then
+                       raise ArgumentError, "Usage: pkg-svr register -n <server name> -d <distribution> -P <package file list> [--gen] [--test] "
                end
                end
-       when "remove"
        when "gen-snapshot"
        when "gen-snapshot"
+               if options[:snaps].empty? then
+                       raise ArgumentError, "Usage: pkg-svr gen-snapshot -n <server name> -d <distribution> -s <snapshot name> [-b <base snapshot name>]"
+               end 
+       when "start"
+               if options[:port].empty? then
+                       raise ArgumentError, "Usage: pkg-svr start -n <server name> -p <port> [-w <password>]"
+               end
+       when "stop"
+               if options[:port].empty? then
+                       raise ArgumentError, "Usage: pkg-svr stop -n <server name> -p <port> [-w <password>]"
+               end
        when "sync"
        when "list"
        when "sync"
        when "list"
+       when "clean"
        else
        else
-               raise ArgumentError, "input option incorrect : #{options[:cmd]}"
+               raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
        end
 end
 
 def option_parse 
     options = {}
        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 <id> -d <distribution> [-u <remote_server_url>] [-l <location>] " + "\n" \
-        + "\t" + "pkg-svr add-dist -i<id> -d <distribution> [-u <remote_server_url>] [-c] " + "\n" \
-        + "\t" + "pkg-svr remove -i <id> " + "\n" \
-        + "\t" + "pkg-svr register -i <id> -d <distribution> -p <binary_package_file_path_list> -s <source_package_file_path_list> [-g] [-t] " + "\n" \
-        + "\t" + "pkg-svr remove-pkg -i <id> -d <distribution> -p <binary_package_name_list> [-o <os>] " + "\n" \
-        + "\t" + "pkg-svr gen-snapshot -i<id> -d <distribution> [-n <snapshot name>] [-b <base_snapshot_name>] [-p <binary_package_file_path_list>] " + "\n"  \
-        + "\t" + "pkg-svr sync -i <id> -d <distribution> [-f] " + "\n"  \
-        + "\t" + "pkg-svr spkg-path -i <id> -d <distribution> -s <source_package_name> " + "\n" \
-        + "\t" + "pkg-svr list [-i <id>] " + "\n" 
-
-    optparse = OptionParser.new do|opts|
+    banner = "Package-server administer service command-line tool." + "\n" \
+        + "\n" + "Usage: pkg-svr <SUBCOMMAND> [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 <server name> -d <distribution> [-u <remote server url>] [-l <location>] " + "\n" \
+        + "\t" + "pkg-svr add-dist -n <server name> -d <distribution> [-u <remote server url>] [--clone] " + "\n" \
+        + "\t" + "pkg-svr add-os -n <server name> -d <distribution> -o <os> " + "\n" \
+        + "\t" + "pkg-svr register -n <server name> -d <distribution> -P <package file list> [--gen] [--test] " + "\n" \
+        + "\t" + "pkg-svr remove -n <server name> " + "\n" \
+        + "\t" + "pkg-svr remove-dist -n <server name> -d <distribution>"  + "\n" \
+        + "\t" + "pkg-svr remove-pkg -n <server name> -d <distribution> -P <package name list> [-o <os>] " + "\n" \
+        + "\t" + "pkg-svr remove-snapshot -n <server name> -d <distribution> -s <snapshot list>" + "\n" \
+        + "\t" + "pkg-svr gen-snapshot -n <server name> -d <distribution> -s <snapshot name> [-b <base snapshot name>] " + "\n"  \
+        + "\t" + "pkg-svr sync -n <server name> -d <distribution> [--force] " + "\n"  \
+        + "\t" + "pkg-svr clean -n <server name> -d <distribution> [-s <snapshot list>] " + "\n" \
+        + "\t" + "pkg-svr start -n <server name> -p <port> [-w <password>]" + "\n" \
+        + "\t" + "pkg-svr stop -n <server name> -p <port> [-w <password>]" + "\n" \
+        + "\t" + "pkg-svr list [-n <server name>] " + "\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 
 
         # Set a banner, displayed at the top
         # of the help screen.
 
                opts.banner = banner 
 
-        opts.on( '-i', '--id <id>', 'package server id' ) do|name|
+        opts.on( '-n', '--name <server name>', 'package server name' ) do|name|
             options[:id] = name 
         end
         
             options[:id] = name 
         end
         
@@ -109,7 +153,7 @@ def option_parse
             options[:dist] = dist 
         end
                
             options[:dist] = dist 
         end
                
-               opts.on( '-u', '--url <server_address>', 'remote server address' ) do|url|
+               opts.on( '-u', '--url <server url>', 'remote server url: http://127.0.0.1/dibs/unstable' ) do|url|
             options[:url] = url 
         end
                
             options[:url] = url 
         end
                
@@ -117,80 +161,89 @@ def option_parse
             options[:os] = os
         end
                
             options[:os] = os
         end
                
-               opts.on( '-p', '--bpackage <binary_pakcage_file_path_list>', 'binary package file path list' ) do|bpkgs|
-            options[:bpkgs] = []
-            list = bpkgs.tr(" \t","").split(",")
+               opts.on( '-P', '--pkgs <package file list>', '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|
             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
                                if l.start_with? "~" then l = Utils::HOME + l.delete("~") end
-                               options[:bpkgs].push l 
+                               options[:pkgs].push l 
             end 
         end
                
             end 
         end
                
-               opts.on( '-s', '--spackage <source_pakcage_file_path_list>', 'source package file path ' ) do|spkgs|
-            options[:spkgs] = []
-            list = spkgs.tr(" \t","").split(",")
-            list.each do |l|
-                               if l.start_with? "~" then l = Utils::HOME + l.delete("~") end
-                               options[:spkgs].push l 
-            end 
+               opts.on( '-s', '--snapshot <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
         end
-               
-               opts.on( '-g', '--generate', 'snapshot is generate' ) do
-            options[:gensnap] = true
-               end
 
 
-               opts.on( '-n', '--sname <snapshot>', 'snapshot name' ) do|snap|
-            options[:snap] = snap 
-        end
-               
-               opts.on( '-b', '--bsnapshot <base_snapshot_name>', 'base snapshot name' ) do|bsnap|
+               opts.on( '-b', '--base <base snapshot>', 'base snapshot name' ) do|bsnap|
             options[:bsnap] = bsnap 
         end
                
             options[:bsnap] = bsnap 
         end
                
-               opts.on( '-l', '--location <location>', 'server location' ) do|loc|
+               opts.on( '-l', '--loc <location>', 'server location' ) do|loc|
             options[:loc] = loc 
         end
                
             options[:loc] = loc 
         end
                
-               opts.on( '-f', '--force', 'force update pkg file' ) do
-            options[:force] = true
+               opts.on( '-p', '--port <port>', 'port number' ) do|port|
+            options[:port] = port
         end
                
         end
                
-               opts.on( '-t', '--test', 'upload for test' ) do
-            options[:test] = true
+               opts.on( '-w', '--passwd <password>', 'password for package server' ) do|passwd|
+            options[:passwd] = passwd
         end
         end
-               
-               opts.on( '-c', '--clone', 'clone mode' ) do
+
+               opts.on( '--clone', 'clone mode' ) do
             options[:clone] = true
         end
             options[:clone] = true
         end
+
+               opts.on( '--force', 'force update pkg file' ) do
+            options[:force] = true
+        end
                
                
-               opts.on( '-h', '--help', 'display this information' ) do
+               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
             puts opts
                        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
     
        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? "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
         if cmd.eql? "help" then ARGV[0] = "-h" end
         options[:cmd] = ARGV[0]
     else
-        raise ArgumentError, banner
+        raise ArgumentError, "Usage: pkg-svr <SUBCOMMAND> [OPTS] or pkg-svr -h"
     end
 
     end
 
-    optparse.parse!
-   
        # default value setting 
        set_default options
        # default value setting 
        set_default options
+    
+       optparse.parse!
 
        # option error check 
        option_error_check options
 
        # option error check 
        option_error_check options
diff --git a/test/a/a b/test/a/a
deleted file mode 100644 (file)
index 7898192..0000000
--- a/test/a/a
+++ /dev/null
@@ -1 +0,0 @@
-a
diff --git a/test/a/package/build.linux b/test/a/package/build.linux
deleted file mode 100755 (executable)
index e056656..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash  -e
-
-clean ()
-{
-    rm -rf $SRCDIR/*.zip
-    rm -rf $SRCDIR/*.tar.gz
-}
-
-build()
-{
-    if [ "`cat $ROOTDIR/b`" = "b" ] 
-    then 
-        echo "A: `cat $ROOTDIR/b` == b ... ok"
-    else
-        echo "A: `cat $ROOTDIR/b` != b ... fail"
-        exit 1
-    fi
-
-    if [ "`cat $ROOTDIR/c`" = "ca" ] 
-    then 
-        echo "A: `cat $ROOTDIR/c` == ca ... ok"
-    else
-        echo "A: `cat $ROOTDIR/c` != ca ... fail"
-        exit 1
-    fi
-}
-
-install()
-{
-    mkdir -p $SRCDIR/package/a.package.linux/data
-    cp $SRCDIR/a $SRCDIR/package/a.package.linux/data
-}
-
-$1
-echo "$1 success"
diff --git a/test/a/package/pkginfo.manifest b/test/a/package/pkginfo.manifest
deleted file mode 100644 (file)
index bb9c561..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: a
-Version: 11
-OS: linux
-Maintainer: xxx
-Build-host-os: linux
-Build-dependency: b [linux], c [linux]
-Source: a
diff --git a/test/b/b b/test/b/b
deleted file mode 100644 (file)
index 6178079..0000000
--- a/test/b/b
+++ /dev/null
@@ -1 +0,0 @@
-b
diff --git a/test/b/package/build.linux b/test/b/package/build.linux
deleted file mode 100755 (executable)
index 83e5a6c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash  -e
-
-clean ()
-{
-    rm -rf $SRCDIR/*.zip
-    rm -rf $SRCDIR/*.tar.gz
-}
-
-build()
-{
-    if [ "`cat $ROOTDIR/c`" = "ca" ] 
-    then 
-        echo "B: `cat $ROOTDIR/c` == ca ... ok"
-    else
-        echo "B: `cat $ROOTDIR/c` != ca ... fail"
-        exit 1
-    fi
-}
-
-install()
-{
-    mkdir -p $SRCDIR/package/b.package.linux/data
-    cp $SRCDIR/b $SRCDIR/package/b.package.linux/data
-}
-
-$1
-echo "$1 success"
diff --git a/test/b/package/pkginfo.manifest b/test/b/package/pkginfo.manifest
deleted file mode 100644 (file)
index a164fd8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: b
-Version: 11
-OS: linux
-Maintainer: xxx
-Build-host-os: linux
-Build-dependency: c [linux]
-Source: b
diff --git a/test/bin/bin_0.0.0_linux.zip b/test/bin/bin_0.0.0_linux.zip
new file mode 100644 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index 0000000..c41dcd8
Binary files /dev/null and b/test/bin/src.tar.gz differ
index 6e47b8c5a3a720c63e09ba5338464fa362993aa8..f3c8c50055001d4078d269b1bc37c4c36058b330 100644 (file)
@@ -3,14 +3,38 @@
 ../build-cli -h
 #POST-EXEC
 #EXPECT
 ../build-cli -h
 #POST-EXEC
 #EXPECT
-Usage: build-cli {build|resolve|query} ...
-       build-cli build -g <git-repository> -c <git-commit> [-d <svr domain>] [-p <svr-port>] [-o <os>] [-a <async>] 
-       build-cli resolve -g <git-repository> -c <git-commit> [-d <svr domain>] [-p <svr-port>] [-o <os>] [-a <async>] 
-       build-cli query [-d <svr domain>] [-p <svr-port>] 
-    -g, --git <git-repository>       git repository
-    -c, --commit <git-commit>        git commit id/tag
-    -d, --domain <build-svr-domain>  remote build server ip address. default 127.0.0.1
-    -p, --port <build-svr-port>      remote build server port. default 2222
-    -o, --os <operating system>      target operating system linux/windows/darwin
-    -a, --async                      asynchronous job
-    -h, --help                       display this information
+Requiest service to build-server command-line tool.
+
+Usage: build-cli <SUBCOMMAND> [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 <project name> -d <server address> [-o <os>] [-w <password>] [--async]
+build-cli resolve -N <project name> -d <server address> [-o <os>] [-w <password>] [--async]
+build-cli query -d <server address>
+build-cli query-system -d <server address>
+build-cli query-project -d <server address>
+build-cli query-job -d <server address>
+build-cli cancel -j <job number> -d <server address> [-w <password>]
+build-cli register -P <file name> -d <server address> -t <ftp server url> [-w <password>]
+
+Options:
+-N, --project <project name>     project name
+-d, --address <server address>   build server address: 127.0.0.1:2224
+-o, --os <operating system>      target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64
+--async                      asynchronous job
+-j, --job <job number>           job number
+-w, --passwd <password>          password for managing project
+-P, --pkg <package file>         package file path
+-t, --ftp <ftp server url>       ftp server url: ftp://dibsftp:dibsftp@127.0.0.1
+-h, --help                       display help
+-v, --version                    display version
index c49e5d13ba2d3379adcd50fc3c174d1a4149cfb1..4b13c124e78566e61177c4048ef83690fec3bdf7 100644 (file)
@@ -1,16 +1,29 @@
 #PRE-EXEC
 #PRE-EXEC
-mkdir buildsvr01
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/emptyserver/unstable -d pkgserver -i emptyserver
-../build-svr start -n testserver3 -p 2223 &
-sleep 1
 #EXEC
 #EXEC
-../build-cli query -d 127.0.0.1 -p 2223
+../build-cli query -d 127.0.0.1:2223
 #POST-EXEC
 #POST-EXEC
-../build-svr stop -n testserver3
-sleep 1
-../build-svr remove -n testserver3
-rm -rf buildsvr01
 #EXPECT
 #EXPECT
-HOST-OS:
-MAX_WORKING_JOBS:
-* JOB *
+* 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) *
index c49e5d13ba2d3379adcd50fc3c174d1a4149cfb1..4641ffbe652107e5c36a67d894743d153ea34fcb 100644 (file)
@@ -1,16 +1,30 @@
 #PRE-EXEC
 #PRE-EXEC
-mkdir buildsvr01
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/emptyserver/unstable -d pkgserver -i emptyserver
-../build-svr start -n testserver3 -p 2223 &
-sleep 1
 #EXEC
 #EXEC
-../build-cli query -d 127.0.0.1 -p 2223
+../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32
 #POST-EXEC
 #POST-EXEC
-../build-svr stop -n testserver3
-sleep 1
-../build-svr remove -n testserver3
-rm -rf buildsvr01
 #EXPECT
 #EXPECT
-HOST-OS:
-MAX_WORKING_JOBS:
-* JOB *
+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-cli-03_1.testcase b/test/build-cli-03_1.testcase
new file mode 100644 (file)
index 0000000..f082adf
--- /dev/null
@@ -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-cli-04.testcase b/test/build-cli-04.testcase
new file mode 100644 (file)
index 0000000..e990744
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+#EXEC
+../build-cli build -N non_exist_project -d 127.0.0.1:2223 -o ubuntu-32
+#POST-EXEC
+#EXPECT
+Error: Requested project does not exist!
+Info: Check project name using "query" command option !
diff --git a/test/build-cli-05.testcase b/test/build-cli-05.testcase
new file mode 100644 (file)
index 0000000..039eb37
--- /dev/null
@@ -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-cli-06.testcase b/test/build-cli-06.testcase
new file mode 100644 (file)
index 0000000..308410f
--- /dev/null
@@ -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-cli-07.testcase b/test/build-cli-07.testcase
new file mode 100644 (file)
index 0000000..d59ca4c
--- /dev/null
@@ -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-cli-08.testcase b/test/build-cli-08.testcase
new file mode 100644 (file)
index 0000000..ff51d73
--- /dev/null
@@ -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-cli-09.testcase b/test/build-cli-09.testcase
new file mode 100644 (file)
index 0000000..676cd46
--- /dev/null
@@ -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-cli-10.testcase b/test/build-cli-10.testcase
new file mode 100644 (file)
index 0000000..7ca3ce7
--- /dev/null
@@ -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-cli-11.testcase b/test/build-cli-11.testcase
new file mode 100644 (file)
index 0000000..87e1de1
--- /dev/null
@@ -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-cli-12.testcase b/test/build-cli-12.testcase
new file mode 100644 (file)
index 0000000..7c4154b
--- /dev/null
@@ -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 "wrong_os_name" is used!
+Error: Check the following supported OS list.
+* ubuntu-32
+* windows-32
diff --git a/test/build-cli-12_1.testcase b/test/build-cli-12_1.testcase
new file mode 100644 (file)
index 0000000..efaa7cf
--- /dev/null
@@ -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 "wrong_os_name" is used!
+Error: Check the following supported OS list.
+* ubuntu-32
+* windows-32
diff --git a/test/build-cli-13.testcase b/test/build-cli-13.testcase
new file mode 100644 (file)
index 0000000..b0bbc1f
--- /dev/null
@@ -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-cli-14.testcase b/test/build-cli-14.testcase
new file mode 100644 (file)
index 0000000..de41149
--- /dev/null
@@ -0,0 +1,9 @@
+#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's password is not matched!
+Error: Use -w option to input your project password
diff --git a/test/build-cli-15.testcase b/test/build-cli-15.testcase
new file mode 100644 (file)
index 0000000..523375a
--- /dev/null
@@ -0,0 +1,9 @@
+#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's password is not matched!
+Error: Use -w option to input your project password
diff --git a/test/build-cli-16.testcase b/test/build-cli-16.testcase
new file mode 100644 (file)
index 0000000..fd31b9a
--- /dev/null
@@ -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-cli-17.testcase b/test/build-cli-17.testcase
new file mode 100644 (file)
index 0000000..230f75e
--- /dev/null
@@ -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-cli-18.testcase b/test/build-cli-18.testcase
new file mode 100644 (file)
index 0000000..136daf7
--- /dev/null
@@ -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-cli-19.testcase b/test/build-cli-19.testcase
new file mode 100644 (file)
index 0000000..f48aab6
--- /dev/null
@@ -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-cli-20.testcase b/test/build-cli-20.testcase
new file mode 100644 (file)
index 0000000..7f048f5
--- /dev/null
@@ -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-cli-21.testcase b/test/build-cli-21.testcase
new file mode 100644 (file)
index 0000000..bd1503a
--- /dev/null
@@ -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-cli-22.testcase b/test/build-cli-22.testcase
new file mode 100644 (file)
index 0000000..6f4e6d5
--- /dev/null
@@ -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-cli-23.testcase b/test/build-cli-23.testcase
new file mode 100644 (file)
index 0000000..9645f35
--- /dev/null
@@ -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-cli-24.testcase b/test/build-cli-24.testcase
new file mode 100644 (file)
index 0000000..e858d32
--- /dev/null
@@ -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-cli-25.testcase b/test/build-cli-25.testcase
new file mode 100644 (file)
index 0000000..a9287f8
--- /dev/null
@@ -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-cli-26.testcase b/test/build-cli-26.testcase
new file mode 100644 (file)
index 0000000..b3c0684
--- /dev/null
@@ -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-cli-27.testcase b/test/build-cli-27.testcase
new file mode 100644 (file)
index 0000000..b40b9b7
--- /dev/null
@@ -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: There is no OS supported by the build server.
diff --git a/test/build-cli-28.testcase b/test/build-cli-28.testcase
new file mode 100644 (file)
index 0000000..04cc21e
--- /dev/null
@@ -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-cli-29.testcase b/test/build-cli-29.testcase
new file mode 100644 (file)
index 0000000..c927bae
--- /dev/null
@@ -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-svr-01.testcase b/test/build-svr-01.testcase
new file mode 100644 (file)
index 0000000..e345367
--- /dev/null
@@ -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://dibsftp:coreps2@172.21.111.132
+#POST-EXEC
+../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Created new build server: "testserver3"
diff --git a/test/build-svr-02.testcase b/test/build-svr-02.testcase
new file mode 100644 (file)
index 0000000..cbedb98
--- /dev/null
@@ -0,0 +1,45 @@
+#PRE-EXEC
+#EXEC
+../build-svr -h
+#POST-EXEC
+#EXPECT
+Build-server administer service command-line tool.
+
+Usage: build-svr <SUBCOMMAND> [OPTS] or build-svr -h
+
+Subcommands:
+       create        Create the build-server.
+       remove        Remove the build-server.
+       start         Start the build-server.
+       stop          Stop the build-server.
+       add-svr       Add build-server for support multi-OS or distribute build job.
+       add-prj       Register information for project what you want build berfore building a project.
+       register      Register the package to the build-server.
+       fullbuild     Build all your projects and upload them to package server.
+
+Subcommand usage:
+       build-svr create -n <server name> -u <package server url> -d <package server address> -t <ftp server url>
+       build-svr remove -n <server name>
+       build-svr start -n <server name> -p <port>
+       build-svr stop -n <server name>
+       build-svr add-svr -n <server name> -d <friend server address>
+       build-svr add-prj -n <server name> -N <project name> [-g <git repository>] [-b <git branch>] [-P <package name>] [-w <password>] [-o <os list>]
+       build-svr add-os -n <server name> -o <os>
+       build-svr register -n <server name> -P <package file>
+       build-svr fullbuild -n <server name>
+
+Options:
+        -n, --name <server name>         build server name
+        -u, --url <package server url>   package server url: http://127.0.0.1/dibs/unstable
+        -d, --address <server address>   server address: 127.0.0.1:2224
+        -p, --port <port>                server port number: 2224
+        -P, --pkg <package name/file>    package file path or name
+        -o, --os <target os list>        ex) linux,windows
+        -N, --pname <project name>       project name
+        -g, --git <git repository>       git repository
+        -b, --branch <git branch>        git branch
+        -w, --passwd <password>          password for managing project
+        -t, --ftp <ftp server url>       ftp server url: ftp://dibsftp:dibsftp@127.0.0.1:1024
+        -h, --help                       display this information
+        -v, --version                    display version
+
diff --git a/test/build-svr-03.testcase b/test/build-svr-03.testcase
new file mode 100644 (file)
index 0000000..6038be5
--- /dev/null
@@ -0,0 +1,13 @@
+#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-svr -n testserver3 -d 127.0.0.1:2223
+cat ~/.build_tools/build_server/testserver3/friends
+#POST-EXEC
+../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Friend server is added successfully!
+127.0.0.1,2223
diff --git a/test/build-svr-04.testcase b/test/build-svr-04.testcase
new file mode 100644 (file)
index 0000000..5a7d65e
--- /dev/null
@@ -0,0 +1,13 @@
+#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
+Test time is elapsed!
diff --git a/test/build-svr-05.testcase b/test/build-svr-05.testcase
new file mode 100644 (file)
index 0000000..634cb10
--- /dev/null
@@ -0,0 +1,14 @@
+#PRE-EXEC
+mkdir buildsvr01
+rm -rf ~/.build_tools/build_server/testserver3
+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 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-svr-06.testcase b/test/build-svr-06.testcase
new file mode 100644 (file)
index 0000000..b0f302a
--- /dev/null
@@ -0,0 +1,10 @@
+#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
+Server is not running!
diff --git a/test/build-svr-07.testcase b/test/build-svr-07.testcase
new file mode 100644 (file)
index 0000000..856e52b
--- /dev/null
@@ -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-svr-08.testcase b/test/build-svr-08.testcase
new file mode 100644 (file)
index 0000000..c18ffa2
--- /dev/null
@@ -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-svr-09.testcase b/test/build-svr-09.testcase
new file mode 100644 (file)
index 0000000..0554f0b
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../build-svr remove -n testserverxx
+#POST-EXEC
+#EXPECT
+does not exist!
diff --git a/test/build-svr-10.testcase b/test/build-svr-10.testcase
new file mode 100644 (file)
index 0000000..126e55f
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../build-svr start -n testserverxx
+#POST-EXEC
+#EXPECT
+does not exist!
diff --git a/test/build-svr-11.testcase b/test/build-svr-11.testcase
new file mode 100644 (file)
index 0000000..1632086
--- /dev/null
@@ -0,0 +1,12 @@
+#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 linux
+#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-svr-12.testcase b/test/build-svr-12.testcase
new file mode 100644 (file)
index 0000000..69e3cd5
--- /dev/null
@@ -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-svr-13.testcase b/test/build-svr-13.testcase
new file mode 100644 (file)
index 0000000..110677a
--- /dev/null
@@ -0,0 +1,11 @@
+#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-prj -n testserver3 -N testa -g test_git -b test_branch -w 1111
+cat buildsvr01/projects/testa/build | grep PASSWD
+#POST-EXEC
+#EXPECT
+Adding project succeeded!
+PASSWD=1111
diff --git a/test/build-svr-14.testcase b/test/build-svr-14.testcase
new file mode 100644 (file)
index 0000000..0d920e9
--- /dev/null
@@ -0,0 +1,12 @@
+#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 linux
+#EXEC
+../build-svr add-prj -n testserver3 -N testx -g test_git -b test_branch -o linux
+#POST-EXEC
+../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Adding project succeeded!
diff --git a/test/build-svr-15.testcase b/test/build-svr-15.testcase
new file mode 100644 (file)
index 0000000..7574a81
--- /dev/null
@@ -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_linux.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-svr-16.testcase b/test/build-svr-16.testcase
new file mode 100644 (file)
index 0000000..d2ade40
--- /dev/null
@@ -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_linux.zip
+#EXEC
+../build-svr register -n testserver3 -P bin/bin_0.0.0_linux.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-svr-17.testcase b/test/build-svr-17.testcase
new file mode 100644 (file)
index 0000000..8f72321
--- /dev/null
@@ -0,0 +1,13 @@
+#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 linux
+cat ~/.build_tools/build_server/testserver3/supported_os_list
+#POST-EXEC
+../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Target OS is added successfully!
+linux
diff --git a/test/build-svr-18.testcase b/test/build-svr-18.testcase
new file mode 100644 (file)
index 0000000..21beedd
--- /dev/null
@@ -0,0 +1,13 @@
+#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 linux
+../build-svr add-os -n testserver3 -o linux
+#POST-EXEC
+../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Target OS is added successfully!
+Target OS already exists in list!
diff --git a/test/build-svr-19.testcase b/test/build-svr-19.testcase
new file mode 100644 (file)
index 0000000..3146917
--- /dev/null
@@ -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 linux
+../build-svr add-os -n testserver3 -o windows
+#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:
+ * linux
+ * windows
diff --git a/test/build-svr-20.testcase b/test/build-svr-20.testcase
new file mode 100644 (file)
index 0000000..460e079
--- /dev/null
@@ -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://dibsftp:coreps2@172.21.111.132
+../build-svr add-os -n testserver3 -o linux
+cp bin/bin_0.0.0_linux.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
index 06947c4fc4944a0f4d2ee4e602cbe7020dedff03..9904eb3e86ed58ea8f8f25cc5c16ac9b1fafaa9d 100644 (file)
@@ -1,2 +1,30 @@
 build-cli-01.testcase
 build-cli-02.testcase
 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
index f908bffe53eb4ab1397ed83f0ce054b5cc415826..d3b6e7a70105562fc4dbaf423a725e2030b49245 100644 (file)
@@ -1,6 +1,18 @@
-buildserver01.testcase
-buildserver02.testcase
-buildserver03.testcase
-buildserver04.testcase
-buildserver05.testcase
-buildserver06.testcase
+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
diff --git a/test/buildserver01.testcase b/test/buildserver01.testcase
deleted file mode 100644 (file)
index fa32179..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#PRE-EXEC
-rm -rf ~/.build_tools/build_server/testserver3
-rm -rf buildsvr01
-mkdir buildsvr01
-#EXEC
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/testserver3/unstable -d pkgserver -i testserver3
-#POST-EXEC
-../build-svr remove -n testserver3
-rm -rf buildsvr01
-#EXPECT
-reated new build server: "testserver3"
diff --git a/test/buildserver02.testcase b/test/buildserver02.testcase
deleted file mode 100644 (file)
index e490e82..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#PRE-EXEC
-#EXEC
-../build-svr -h
-#POST-EXEC
-#EXPECT
-Usage: build-svr {create|remove|start|build|help} ...
-       build-svr create -n <name> -u <pkg-server-url> -d <pkg-server-domain> -i <pkg-server-id>
-       build-svr remove -n <name>
-       build-svr start -n <name> [-p <port]
-       build-svr stop -n <name> 
-       build-svr add -n <name> [-d <frined-svr-domain> -p <friend-svr port>]
-    -n, --name <name>                build server name
-    -u, --url <pkg-server-url>       package server URL: http://xxx/yyy/zzz
-    -d <pkg/friend-svr domain>       package svr or friend svr ip or ssh alias
-        --domain
-    -i, --id <pkg-server-id>         package server id
-    -p, --port <port>                port
-    -h, --help                       display this information
diff --git a/test/buildserver03.testcase b/test/buildserver03.testcase
deleted file mode 100644 (file)
index de131bf..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#PRE-EXEC
-rm -rf buildsvr01
-mkdir buildsvr01
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/testserver3/unstable -d pkgserver -i testserver3
-#EXEC
-../build-svr add -n testserver3 -d 127.0.0.1 -p 2223
-cat ~/.build_tools/build_server/testserver3/friends
-#POST-EXEC
-../build-svr remove -n testserver3
-rm -rf buildsvr01
-#EXPECT
-Friend server is added successfully!
-127.0.0.1,2223
diff --git a/test/buildserver04.testcase b/test/buildserver04.testcase
deleted file mode 100644 (file)
index bdad4d1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#PRE-EXEC
-rm -rf buildsvr01
-mkdir buildsvr01
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/emptyserver/unstable -d pkgserver -i emptyserver
-#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
-Test time is elapsed!
diff --git a/test/buildserver05.testcase b/test/buildserver05.testcase
deleted file mode 100644 (file)
index d15c978..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#PRE-EXEC
-rm -rf buildsvr01
-mkdir buildsvr01
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/emptyserver/unstable -d pkgserver -i emptyserver
-../build-svr start -n testserver3 -p 2223 &
-#EXEC
-sleep 2
-../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/buildserver06.testcase b/test/buildserver06.testcase
deleted file mode 100644 (file)
index d95913d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#PRE-EXEC
-mkdir buildsvr01
-cd buildsvr01; ../../build-svr create -n testserver3 -u http://172.21.111.132/emptyserver/unstable -d pkgserver -i emptyserver
-#EXEC
-../build-svr stop -n testserver3
-#POST-EXEC
-../build-svr remove -n testserver3
-rm -rf buildsvr01
-#EXPECT
-Server is not running!
diff --git a/test/buildsvr.init b/test/buildsvr.init
new file mode 100644 (file)
index 0000000..5b294f6
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+rm -rf buildsvr01
+rm -rf ~/.build_tools/build_server/testserver3
+mkdir buildsvr01
+cd buildsvr01
+../../build-svr remove -n testserver3
+../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://ftpuser:ftpuser@127.0.0.1
+../../build-svr add-svr -n testserver3 -d 127.0.0.1:2224
+../../build-svr add-svr -n testserver3 -u `pwd`/../pkgsvr02/unstable 
+cd ..
+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 ..
+../build-svr add-os -n testserver3 -o ubuntu-32
+../build-svr add-os -n testserver3 -o windows-32
+../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master
+../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master
+../build-svr add-prj -n testserver3 -N testc -g `pwd`/git01/c -b master -w 1111
+../build-svr add-prj -n testserver3 -N testd -g `pwd`/git01/d -b master -o ubuntu-32
+../build-svr add-prj -n testserver3 -N teste -P bin
+../build-svr add-prj -n testserver3 -N testa1 -g `pwd`/git01/a1 -b master
+../pkg-svr register -n pkgsvr01 -d unstable -P bin/bin_0.0.0_ubuntu-32.zip
+../build-svr start -n testserver3 -p 2223
diff --git a/test/c/c b/test/c/c
deleted file mode 100644 (file)
index 16fc679..0000000
--- a/test/c/c
+++ /dev/null
@@ -1 +0,0 @@
-ca
diff --git a/test/c/package/build.linux b/test/c/package/build.linux
deleted file mode 100755 (executable)
index b774e2d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash  -e
-
-clean ()
-{
-    rm -rf $SRCDIR/*.zip
-    rm -rf $SRCDIR/*.tar.gz
-}
-
-build ()
-{
-    echo "C: clean build (no dependency) ok"
-}
-
-install ()
-{
-    mkdir -p $SRCDIR/package/c.package.linux/data
-    cp $SRCDIR/c $SRCDIR/package/c.package.linux/data
-}
-
-$1
-echo "$1 success"
diff --git a/test/c/package/pkginfo.manifest b/test/c/package/pkginfo.manifest
deleted file mode 100644 (file)
index ede7a91..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Package: c
-Version: 11
-OS: linux
-Build-host-os: linux
-Maintainer: xx
-Source: c
diff --git a/test/git01/a.tar.gz b/test/git01/a.tar.gz
new file mode 100644 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index 0000000..c0a3a6e
Binary files /dev/null and b/test/git01/d_v0.tar.gz differ
index d63bc7eaf528f4062b4d79fc9f4a6de0bef5dedf..7fe78d722bec05dbf68e8a8dba576663c2db8c1c 100644 (file)
@@ -1,5 +1,6 @@
 packageserver01.testcase
 packageserver02.testcase
 packageserver01.testcase
 packageserver02.testcase
+packageserver24.testcase
 packageserver03.testcase
 packageserver04.testcase
 packageserver05.testcase
 packageserver03.testcase
 packageserver04.testcase
 packageserver05.testcase
@@ -7,9 +8,7 @@ packageserver06.testcase
 packageserver07.testcase
 packageserver08.testcase
 packageserver09.testcase
 packageserver07.testcase
 packageserver08.testcase
 packageserver09.testcase
-packageserver10.testcase
 packageserver11.testcase
 packageserver11.testcase
-packageserver12.testcase
 packageserver13.testcase
 packageserver14.testcase
 packageserver15.testcase
 packageserver13.testcase
 packageserver14.testcase
 packageserver15.testcase
index d0adec595150fcf45de7bf5243c88877d56d6eef..f1c411e7ce506850f91dded9bad3c7e640d2febd 100644 (file)
@@ -3,30 +3,60 @@
 ../pkg-svr -h
 #POST-EXEC
 #EXPECT
 ../pkg-svr -h
 #POST-EXEC
 #EXPECT
-Usage: pkg-svr {create|register|gen-snapshot|sync|add-dist|spkg-path|remove|remove-pkg|list|help} ...
-       pkg-svr create -i <id> -d <distribution> [-u <remote_server_url>] [-l <location>] 
-       pkg-svr add-dist -i<id> -d <distribution> [-u <remote_server_url>] [-c] 
-       pkg-svr remove -i <id> 
-       pkg-svr register -i <id> -d <distribution> -p <binary_package_file_path_list> -s <source_package_file_path_list> [-g] [-t] 
-       pkg-svr remove-pkg -i <id> -d <distribution> -p <binary_package_name_list> 
-       pkg-svr gen-snapshot -i<id> -d <distribution> [-n <snapshot name>] [-b <base_snapshot_name>] [-p <binary_package_file_path_list>] 
-       pkg-svr sync -i <id> -d <distribution> [-f] 
-       pkg-svr spkg-path -i <id> -d <distribution> -s <source_package_name> 
-       pkg-svr list [-i <id>] 
-    -i, --id <id>                    package server id
-    -d, --dist <distribution>        package server distribution
-    -u, --url <server_address>       remote server address
-    -o, --os <operating system>      target operating system
-    -p <binary_pakcage_file_path_list>
-        --bpackage                   binary package file path list
-    -s <source_pakcage_file_path_list>
-        --spackage                   source package file path 
-    -g, --generate                   snapshot is generate
-    -n, --sname <snapshot>           snapshot name
-    -b <base_snapshot_name>          base snapshot name
-        --bsnapshot
-    -l, --location <location>        server location
-    -f, --force                      force update pkg file
-    -t, --test                       upload for test
-    -c, --clone                      clone mode
-    -h, --help                       display this information
+Package-server administer service command-line tool.
+
+Usage: pkg-svr <SUBCOMMAND> [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 <server name> -d <distribution> [-u <remote server url>] [-l <location>] 
+pkg-svr add-dist -n <server name> -d <distribution> [-u <remote_server_url>] [--clone] 
+pkg-svr add-os -n <server name> -d <distribution> -o <os> 
+pkg-svr register -n <server name> -d <distribution> -P <package file list> [--gen] [--test] 
+pkg-svr link -n <server name> -d <distribution> --origin-pkg-name <origin pkg name> --origin-pkg-os <origin pkg os> --link-os-list <link os list>
+pkg-svr remove -n <server name> 
+pkg-svr remove-dist -n <server name> -d <distribution>
+pkg-svr remove-pkg -n <server name> -d <distribution> -P <package name list> [-o <os>] 
+pkg-svr remove-snapshot -n <server name> -d <distribution> -s <snapshot list>
+pkg-svr gen-snapshot -n <server name> -d <distribution> -s <snapshot name> [-b <base snapshot name>] 
+pkg-svr sync -n <server name> -d <distribution> [--force] 
+pkg-svr clean -n <server name> -d <distribution> [-s <snapshot list>] 
+pkg-svr start -n <server name> -p <port>
+pkg-svr stop -n <server name> -p <port>
+pkg-svr list [-n <server name>] 
+
+Options:
+-n, --name <server name>         package server name
+-d, --dist <distribution>        package server distribution
+-u, --url <server url>           remote server url: http://127.0.0.1/dibs/unstable
+-o, --os <operating system>      target operating system
+-P, --pkgs <package file list>   package file path list
+-s, --snapshot <snapshot>        a snapshot name or snapshot list
+-b, --base <base snapshot>       base snapshot name
+-l, --loc <location>             server location
+-p, --port <port>                port number
+    --clone                      clone mode
+    --force                      force update pkg file
+    --test                       upload for test
+    --gen                        generate snapshot
+    --origin-pkg-name <origin_pkg_name>
+                                 origin package name
+    --origin-pkg-os <origin_pkg_os>
+                                 origin package os
+    --link-os-list <link_os_list>
+                                 target os list to link origin file
+-h, --help                       display help
+-v, --version                    display version
index dd533bd494e03331649b24abc08519f565aed7b3..408ca26ac814e1745beaae81afef45767fdc2660 100644 (file)
@@ -1,6 +1,7 @@
 #PRE-EXEC
 #PRE-EXEC
+../pkg-svr remove -n temp_local --force
 #EXEC
 #EXEC
-../pkg-svr create -i temp_local -d unstable 
+../pkg-svr create -n temp_local -d unstable 
 #POST-EXEC
 #EXPECT
 package server [temp_local] created successfully
 #POST-EXEC
 #EXPECT
 package server [temp_local] created successfully
index e858351ad6a2c6450dcb03ed7bb3a45387e932aa..11eb7742407682f32228ad5376189137959396d4 100644 (file)
@@ -1,6 +1,8 @@
 #PRE-EXEC
 #PRE-EXEC
+../pkg-svr remove -n temp_remote --force
 #EXEC
 #EXEC
-../pkg-svr create -i temp_remote -d unstable -u http://172.21.111.177/tmppkgsvr/tmp
+../pkg-svr create -n temp_remote -d unstable -u http://172.21.111.177/tmppkgsvr/tmp
 #POST-EXEC
 #EXPECT
 #POST-EXEC
 #EXPECT
+snapshot is generated : 
 package server [temp_remote] created successfully
 package server [temp_remote] created successfully
index f2539ca33f2724d33a5796c71a6f9b9d935bb114..3be625764cb944577cb753342fd1df20de8a328c 100644 (file)
@@ -1,6 +1,7 @@
 #PRE-EXEC
 #PRE-EXEC
+../pkg-svr remove -n temp_remote_dup --force
 #EXEC
 #EXEC
-../pkg-svr create -i temp_remote_dup -d unstable -u temp_remote/unstable
+../pkg-svr create -n temp_remote_dup -d unstable -u temp_remote/unstable
 #POST-EXEC
 #EXPECT
 package server [temp_remote_dup] created successfully
 #POST-EXEC
 #EXPECT
 package server [temp_remote_dup] created successfully
index a66a04038632b1487384f32b202c5bbb117f3dc8..da0ad18d32c7e93ff601a731ce35cbb0341e0c8c 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr add-dist -i temp_local -d stable 
+../pkg-svr add-dist -n temp_local -d stable 
 #POST-EXEC
 #EXPECT
 distribution [stable] added successfully
 #POST-EXEC
 #EXPECT
 distribution [stable] added successfully
index 9f9e9174d3a73b6061faf5f21d019ea5b6e153ad..cf49f46d726d6c4aac821ed89bacb54b4bed191b 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr sync -i temp_remote -d unstable 
+../pkg-svr sync -n temp_remote -d unstable 
 #POST-EXEC
 #EXPECT
 #POST-EXEC
 #EXPECT
-package server [temp_remote]'s distribution [unstable] has the synchronization.
+package server [temp_remote]'s distribution [unstable] has been synchronized.
index 1b7d84c8f1c8ab3869c09c902514336c6c4e6aa3..13bec0c63f9c3adfd19cf04391a03971119b5497 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr sync -i temp_remote_dup -d unstable -f
+../pkg-svr sync -n temp_remote_dup -d unstable --force
 #POST-EXEC
 #EXPECT
 #POST-EXEC
 #EXPECT
-package server [temp_remote_dup]'s distribution [unstable] has the synchronization.
+package server [temp_remote_dup]'s distribution [unstable] has been synchronized.
index 9ecc71a880955ad0eab854193c69d6a6cf634dfb..db9a935e4c4b0f5cdb2690d2b7346ebfa35580a3 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr gen-snapshot        -i temp_remote
+../pkg-svr gen-snapshot        -n temp_remote -s snap01
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
index 547b101ff7a1b06d4b7c9d3b1f818bb57b75445f..d8632bf7d24359ed5fd9c814accb28acf27e88f8 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr gen-snapshot -i temp_remote -d unstable 
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s snap02
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
index 34ca9b6e01d7c660d6eceb333c33d22ea96c100b..7a5fcb2eb2caab96e3060ebc127a33ad7cfbb8a1 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr gen-snapshot -i temp_remote -d unstable -n test
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s test
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
index a7ba03165fcac49fe3fc9aad3876dbe43f8b294c..247141f1c43e9589c4d8a7281ff50d800d3bd168 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr gen-snapshot -i temp_remote -d unstable -n test2 -b test 
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s snap03 -b snap01
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
index e5db467f3c1b2d9c90f8de67e1512196c0de5453..092eb4e2d6bbd814ef47ca43af6b9c95a2df3a5a 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../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 -s test3
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
 #POST-EXEC
 #EXPECT
 snapshot is generated : 
index 017edb2996aaa5c2eff8581ef1596c89222b4b81..ae8c629e3ee89c63f2e5402ea3d0b096309f555e 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../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/snap01
 #POST-EXEC
 #EXPECT
 package server [temp_remote_snap] created successfully
 #POST-EXEC
 #EXPECT
 package server [temp_remote_snap] created successfully
index 62d6676812557c5f2475754ca50c82474f4eadc9..06bdd06c37380598912d7b0515cbb4d05e5dfbbb 100644 (file)
@@ -1,7 +1,7 @@
 #PRE-EXEC
 cp test_server_pkg_file/smart-build-interface* ./
 #EXEC
 #PRE-EXEC
 cp test_server_pkg_file/smart-build-interface* ./
 #EXEC
-../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
+../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen
 #POST-EXEC
 #EXPECT
 package registed successfully
 #POST-EXEC
 #EXPECT
 package registed successfully
index 351d6aa38e1dc1f23e251a26550a855208fdf7d7..af34b96d7b61c3cb59f9b31ca246e91a410713e8 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../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
+../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
 #POST-EXEC
 #EXPECT
 existing package's version is higher than register package
index a70d2508a43a098837ed38296cbee4beda41a671..4d0977624b77247ee6a5d17cc1d133c2eb5ebae0 100644 (file)
@@ -1,7 +1,7 @@
 #PRE-EXEC
 cp test_server_pkg_file/smart-build-interface* ./
 #EXEC
 #PRE-EXEC
 cp test_server_pkg_file/smart-build-interface* ./
 #EXEC
-../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
+../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
 #POST-EXEC
 #EXPECT
 package registed successfully
index 75ca498cee2cac79eff4fc60e2a11913d98f34dc..ad1549b751cd9939786a34146c52949b2f9d7867 100644 (file)
@@ -1,7 +1,7 @@
 #PRE-EXEC
 cp test_server_pkg_file/smart-build-interface* ./
 #EXEC
 #PRE-EXEC
 cp test_server_pkg_file/smart-build-interface* ./
 #EXEC
-../pkg-svr remove-pkg -i temp_local -d unstable -p smart-build-interface
+../pkg-svr remove-pkg -n temp_local -d unstable -P smart-build-interface
 #POST-EXEC
 #EXPECT
 package removed successfully
 #POST-EXEC
 #EXPECT
 package removed successfully
index d144662f02faed097a64205ce3a8cd2aad601fe8..cd5b36b1823639e7669163e5b5578ea685e9709d 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr list -i temp_local
+../pkg-svr list -n temp_local
 #POST-EXEC 
 rm smart-build-interface_1.20.1*
 #EXPECT 
 #POST-EXEC 
 rm smart-build-interface_1.20.1*
 #EXPECT 
index 4747a48d0b5ab92a2eaa883c42a2a12a1a98354c..7d47e528aa273ef91ad98c2c1371f940b7186231 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr remove -i temp_local -f
+../pkg-svr remove -n temp_local --force
 #POST-EXEC 
 YES
 #EXPECT
 #POST-EXEC 
 YES
 #EXPECT
index 2fc8eb93a6ef28a14de2f6028d82b9ab733428f8..1ae0b53f03d0c7079e776c4b303f966d3e48de25 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr remove -i temp_remote -f
+../pkg-svr remove -n temp_remote --force
 #POST-EXEC 
 YES
 #EXPECT
 #POST-EXEC 
 YES
 #EXPECT
index f63decb2710da30ec23b81185286c042e8c69ccc..3dad192dba489abb385f14f2b81e7db172dec61a 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr remove -i temp_remote_dup -f
+../pkg-svr remove -n temp_remote_dup --force
 #POST-EXEC 
 YES
 #EXPECT
 #POST-EXEC 
 YES
 #EXPECT
index c92b0b97cb99d4a06dd52d7ad5b366fb3e5c9b76..6e37f2fc20ff3d68e94858a14b56d3922f32bbff 100644 (file)
@@ -1,6 +1,6 @@
 #PRE-EXEC
 #EXEC
 #PRE-EXEC
 #EXEC
-../pkg-svr remove -i temp_remote_snap -f
+../pkg-svr remove -n temp_remote_snap --force
 #POST-EXEC 
 YES
 #EXPECT
 #POST-EXEC 
 YES
 #EXPECT
diff --git a/test/packageserver24.testcase b/test/packageserver24.testcase
new file mode 100644 (file)
index 0000000..2657bab
--- /dev/null
@@ -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 (file)
index 0000000..e399ad8
--- /dev/null
@@ -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
index e4f6b2c40b9c78b518859ba9f860e83d8cc6af8d..f4e41d16e7ef41d979bffaff6d9258b6774b950b 100644 (file)
@@ -7,4 +7,4 @@ ls pkgcli01
 #POST-EXEC
 rm -rf pkgcli01
 #EXPECT
 #POST-EXEC
 rm -rf pkgcli01
 #EXPECT
-base-ide-product_0.20.8_linux.zip
+base-ide-product_1.0.2_linux.zip
index 6a74ae7cc3bc397e83b700dc8bb47ba150ee28a3..84bf7510b39ad18e24afd19a73d6b22fac94e485 100644 (file)
@@ -3,4 +3,4 @@
 ../pkg-cli list-rpkg -u http://172.21.111.132/testserver3/unstable
 #POST-EXEC
 #EXPECT
 ../pkg-cli list-rpkg -u http://172.21.111.132/testserver3/unstable
 #POST-EXEC
 #EXPECT
-base-ide-product  (0.20.8)
+base-ide-product  (1.0.2)
index 443aa3e0f56fac20c2b3a98107b47b3c5d597df2..fc5cf62a93f71a876ed62d02e0a580215280f89e 100644 (file)
@@ -4,5 +4,5 @@
 #POST-EXEC
 #EXPECT
 Package : base-ide-product
 #POST-EXEC
 #EXPECT
 Package : base-ide-product
-Version : 0.20.8
+Version : 1.0.2
 OS : linux
 OS : linux
index cf646288b6dfb5efea8a1c7a123310f01d300b9b..74d4baacd708e59235399576ca0b03ccf695f14a 100644 (file)
@@ -1,24 +1,23 @@
-Package : A
+Source : Origin
 Version : 0.1.0
 Version : 0.1.0
+Maintainer : taejun.ha <tajun.ha@samsung.com>
+
+Package : A
 OS : linux
 OS : linux
+C-test : test
 Build-host-os :linux | windows | darwin
 Build-host-os :linux | windows | darwin
-Maintainer : taejun.ha <tajun.ha@samsung.com>
 Path : binary/A_0.1.0_linux.zip
 Path : binary/A_0.1.0_linux.zip
+C-commic : ask
 Origin : remote
 Origin : remote
-SHA256 : 52b400554f2a29dec46144af649181cf287c000b4feb65de72055ed9f11924a9
+C-origin : kkk
 
 Package: B
 
 Package: B
-Version : 0.2.0
 OS : linux
 Build-host-os :linux | windows | darwin
 OS : linux
 Build-host-os :linux | windows | darwin
-Maintainer : taejun.ha <tajun.ha@samsung.com>
 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 : 
 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 
 SHA256 : your_checksum
 Description : this is my first 
-project
-descriotion 
+C-kim : oks
diff --git a/test/pkg-list-local b/test/pkg-list-local
new file mode 100644 (file)
index 0000000..ce331b6
--- /dev/null
@@ -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/pkgsvr.init b/test/pkgsvr.init
new file mode 100644 (file)
index 0000000..96b4f3f
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+rm -rf ~/.build_tools/pkg_server/pkgsvr01
+rm -rf `pwd`/pkgsvr01
+ruby -d ../pkg-svr create -n pkgsvr01 -d unstable
+ruby -d ../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32
+ruby -d ../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32
+ruby -d ../pkg-svr start -n pkgsvr01 -p 3333
diff --git a/test/pkgsvr2.init b/test/pkgsvr2.init
new file mode 100644 (file)
index 0000000..e97681c
--- /dev/null
@@ -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
index 7085799e51e2cf214bc05870da9c7783678592b7..177cf4d5d6fc387df647ef896f81667eddb5d9f0 100755 (executable)
@@ -22,15 +22,13 @@ class TestCase
        end
 
        def is_succeeded?(results)
        end
 
        def is_succeeded?(results)
+               i = 0
                @expected_results.each do |e|
                        found = false
                @expected_results.each do |e|
                        found = false
-                       results.each do |r|
-                               if r.include? e then
-                                       found = true
-                                       break
-                               end     
+                       if not results[i].include? e then
+                               return false
                        end
                        end
-                       if not found then return false end
+                       i += 1
                end     
 
                return true
                end     
 
                return true
@@ -88,12 +86,19 @@ def execute( file_name )
                        cmd = cmd[0..-2]
                        fork_p = true   
                end
                        cmd = cmd[0..-2]
                        fork_p = true   
                end
+
                # get result
                if not fork_p then
                        IO.popen("#{cmd} 2>&1") { |io|
                # 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|
                        }
                else
                        IO.popen("#{cmd} 2>&1 &") { |io|
+               #               io.each do |line|
+               #                       puts "---> #{line}"
+               #               end
                        }
                end
                #`#{cmd}`
                        }
                end
                #`#{cmd}`
@@ -102,12 +107,36 @@ def execute( file_name )
        # exec
        results = []
        tcase.exec_cmds.each do |cmd|
        # 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
                # get result
-               IO.popen("#{cmd} 2>&1") { |io|
-                       io.each do |line|
-                               results.push line.strip
-                       end
-               }
+               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
        end
 
        # check expected result
diff --git a/test/test_bserver2c.rb b/test/test_bserver2c.rb
deleted file mode 100755 (executable)
index 0d59deb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/ruby 
-
-require File.dirname(__FILE__) + "/../src/build_server/BuildServerController"
-
-BuildServerController.build_git("mbs_server","gerrithost:/slp/sdk/public/native/toolchain/smart-build-interface","origin/unstable","linux", nil)
-
-#BuildServerController.build_local("temp","/home/bluleo78/git/sbi-slp-public-plugin/toolchains/public/gdb_build","linux")
-=begin
-#case ARGV[0]
-#      when "create" then
-#              pkg_server.create "temp", "unstable", "http://172.21.111.132/pkgserver/", "unstable"
-#      when "register" then
-#              #pkg_server.register "/home/taejun/project/sdk-build/test/smart-build-interface_0.19.1_linux.zip", "unstable", "-g"
-#              pkg_server.register "/home/taejun/project/sdk-build/test/smart-build-interface_0.19.1_linux.zip", "unstable", ""
-#      when "snapshot" then 
-               pkg_server.snapshot_generate "", "unstable", "", "", ""
-       when "sync" then
-       #       pkg_server.sync "unstable", "force"
-               pkg_server.sync "unstable", ""
-       when "add_distribution" then
-               pkg_server.add_distribution "test_stable", "stable"
-       else
-               puts "First input error : #{ARGV[0]}"
-end
-=end
diff --git a/test/test_bserver3c.rb b/test/test_bserver3c.rb
deleted file mode 100755 (executable)
index 28b1564..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/ruby 
-
-require File.dirname(__FILE__) + "/../src/common/utils"
-require File.dirname(__FILE__) + "/../src/build_server/BuildServerController"
-$SERVER_CONFIG_ROOT = Utils::HOME + "/.tizen_build_server"
-
-#BuildServerController.build_git("temp","gerrithost:/slp/sdk/public/native/toolchain/smart-build-interface","origin/unstable","linux")
-sleep 5
-
-BuildServerController.build_local("temp","/home/bluleo78/git/sbi-slp-public-plugin/toolchains/public/gdb_build","linux","/home/bluleo78/test/test/unstable")
-=begin
-#case ARGV[0]
-#      when "create" then
-#              pkg_server.create "temp", "unstable", "http://172.21.111.132/pkgserver/", "unstable"
-#      when "register" then
-#              #pkg_server.register "/home/taejun/project/sdk-build/test/smart-build-interface_0.19.1_linux.zip", "unstable", "-g"
-#              pkg_server.register "/home/taejun/project/sdk-build/test/smart-build-interface_0.19.1_linux.zip", "unstable", ""
-#      when "snapshot" then 
-               pkg_server.snapshot_generate "", "unstable", "", "", ""
-       when "sync" then
-       #       pkg_server.sync "unstable", "force"
-               pkg_server.sync "unstable", ""
-       when "add_distribution" then
-               pkg_server.add_distribution "test_stable", "stable"
-       else
-               puts "First input error : #{ARGV[0]}"
-end
-=end
index c299f7f388b2b659dc9369c81a53612c948afd2a..767dc8c2a88c3038cb395545b1cb1e71c88e6a58 100755 (executable)
@@ -2,8 +2,7 @@
 require '../src/common/parser'
 require '../src/common/package'
 
 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-local"
+alist.each do |l|
     l.print
     l.print
-end 
+end
index cb17835f4d7250399c72e275ff45a989b6ccaf9e..c3f18a0ce30d84c29faa00277825d5eb0d961509 100755 (executable)
@@ -1,63 +1,66 @@
 #!/bin/sh 
 
 echo "============ remove 1 =============="
 #!/bin/sh 
 
 echo "============ remove 1 =============="
-../pkg-svr remove -i temp_local
+../pkg-svr remove -n temp_local --force
 echo "============ remove 2 =============="
 echo "============ remove 2 =============="
-../pkg-svr remove -i temp_remote
+../pkg-svr remove -n temp_remote --force
 echo "============ remove 3 =============="
 echo "============ remove 3 =============="
-../pkg-svr remove -i temp_remote_dup
+../pkg-svr remove -n temp_remote_dup --force
 echo "============ remove 4 =============="
 echo "============ remove 4 =============="
-../pkg-svr remove -i temp_remote_snap
+../pkg-svr remove -n temp_remote_snap --force
 echo "============ create 1 =============="
 echo "============ create 1 =============="
-../pkg-svr create -i temp_local -d unstable 
+../pkg-svr create -n temp_local -d unstable 
 echo "============ create 2 =============="
 echo "============ create 2 =============="
-../pkg-svr create -i temp_remote -d unstable -u http://172.21.17.55/dibs/unstable
+../pkg-svr create -n temp_remote -d unstable -u http://172.21.17.55/private/develop
 echo "============ create 3 =============="
 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 =============="
 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 =============="
 echo "============ sync 1 =============="
-../pkg-svr sync -i temp_remote -d unstable 
+../pkg-svr sync -n temp_remote -d unstable 
 echo "============ sync 2 =============="
 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 =============="
 echo "============ gen snapshot 1 =============="
-../pkg-svr gen-snapshot        -i temp_remote
+../pkg-svr gen-snapshot        -n temp_remote
 echo "============ gen snapshot 2 =============="
 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 =============="
 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 =============="
 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 =============="
 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 =============="
 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 =============="
 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 =============="
 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 =============="
 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 =============="
 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 =============="
 echo "============ register 1 =============="
-cp test_server_pkg_file/smart-build-interface* ./
-../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 =============="
 echo "============ register 2 =============="
-../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 =============="
 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 ==============" 
 echo "============ remove 3 ==============" 
-../pkg-svr remove-pkg -i temp_local -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 =============="
 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_windows.zip 
-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 (file)
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.tar.gz b/test/test_server_pkg_file/smart-build-interface_1.20.1.tar.gz
deleted file mode 100644 (file)
index 96f13b4..0000000
Binary files a/test/test_server_pkg_file/smart-build-interface_1.20.1.tar.gz and /dev/null differ
index 109a1441f2e8f0886379fe411d93b59602e30e58..cc2a217be42c4fc3ef3b9b362f42f5521eac6002 100644 (file)
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
index 5f9d7ead161ac1fc080be9d7b34caa1e73d339f9..6a044597998df8736d9374c573ab4395c087b1bb 100644 (file)
@@ -16,7 +16,11 @@ GIT_LIST="
 /sdk/ide/common-eplugin
 /sdk/ide/eventinjector-eplugin
 /sdk/ide/nativecommon-eplugin
 /sdk/ide/common-eplugin
 /sdk/ide/eventinjector-eplugin
 /sdk/ide/nativecommon-eplugin
+/sdk/ide/nativeappcommon-eplugin
 /sdk/ide/nativeapp-eplugin
 /sdk/ide/nativeapp-eplugin
+/sdk/ide/nativecpp-eplugin
+/sdk/ide/nativecpp-ext-eplugin
+/sdk/ide/native-sample
 /sdk/ide/nativeplatform-eplugin
 /sdk/ide/unittest-eplugin
 /sdk/ide/native-gui-builder-eplugin
 /sdk/ide/nativeplatform-eplugin
 /sdk/ide/unittest-eplugin
 /sdk/ide/native-gui-builder-eplugin
@@ -185,6 +189,33 @@ function git_checkout_all() {
        cd ${START_PATH}
 }
 
        cd ${START_PATH}
 }
 
+## Command git
+function git_command() {
+       GIT_PATH=$1
+       GIT_NAME=${GIT_PATH##*/}
+
+       ## ARG1 : <source directory>
+       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
 ###############################################################
 ###############################################################
 ## Begin script
 ###############################################################
@@ -228,7 +259,12 @@ case ${SCRIPT_OPERATION} in
 
        ## process default
        *)
 
        ## process default
        *)
-               usage
+               if [ "$#" == 1 ]; then
+                       ARG1=$(pwd)
+                       git_command_all
+               else
+                       usage
+               fi
                ;;
 esac
 
                ;;
 esac
 
diff --git a/upgrade b/upgrade
new file mode 100644 (file)
index 0000000..b93eefe
--- /dev/null
+++ b/upgrade
@@ -0,0 +1,256 @@
+#!/usr/bin/ruby
+=begin
+ upgrade
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <taejun.ha@samsung.com>
+Jiil Hyoun <jiil.hyoun@samsung.com>
+Donghyuk Yang <donghyuk.yang@samsung.com>
+DongHee Yang <donghee.yang@samsung.com>
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+
+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 "utils.rb"
+require "log.rb"
+require "BuildServerController"
+require "packageServerLog"
+
+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 <dibs path> -S -t <server type> -n <server name> -p <server port>" + "\n"
+               end
+       else
+       if options[:locate].nil? or options[:url].nil? then
+                       raise ArgumentError, "upgrade -u <package server url> [-l <dibs path>]"  + "\n" 
+               end
+    end
+end
+
+def option_parse 
+    options = {}
+    banner = "DIBS upgrade service command-line tool." + "\n" \
+       + "\n" + "Usage: upgrade -u <package server url> [-l <dibs path>]" + "\n" \
+       + "\n" + "Options:" + "\n"
+
+    optparse = OptionParser.new(nil, 32, ' '*8) do|opts|
+               opts.banner = banner 
+
+               options[:locate] = File.dirname(__FILE__)
+        opts.on( '-l', '--locate <dibs path>', 'located dibs path' ) do|locate|
+            options[:locate] = locate
+        end
+
+               opts.on( '-u', '--url <package server 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 <server type>', 'sever type : BUILDSERVER or PACKAGESERVER' ) do|type|
+            options[:type] = type
+        end
+
+        opts.on( '-n', '--name <server name>', 'build server name or package server  name' ) do|name|
+            options[:name] = name 
+        end
+
+        options[:port] = 2222
+               opts.on( '-p', '--port <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 <dibs path>, located dibs path"
+                       puts "  -u, --url <package server 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]
+
+       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}"
+       BUILD_FRIENDS_FILE = "#{BUILD_CONFIG_ROOT}/friends"
+
+       if not File.exist? BACKUP_ROOT then FileUtils.mkdir_p(BACKUP_ROOT) end
+       log = PackageServerLog.new( "#{BACKUP_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}"
+               else
+                       cmd = "#{UPGRADE_CMD} -I -l #{dibs_path} -u #{pkg_svr_url}"
+               end
+
+               cmd = Utils.execute_shell_generate(cmd)
+               Utils.spawn(cmd)
+
+       else
+               # Get SERVER INFORMATION
+               if start_opt and svr_type.eql? "BUILDSERVER" then
+                       build_server = BuildServerController.get_server(svr_name)
+                       pkg_svr_url = build_server.pkgserver_url
+                       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 svr_type.eql? "BUILDSERVER" then
+                               # get friends server information
+                               if File.exist? BUILD_FRIENDS_FILE then
+                                       File.open( BUILD_FRIENDS_FILE, "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
+                       
+                                                       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
+                                                       if build_client.send "UPGRADE|#{build_server.password}" then
+                                                               # recevie & print
+                                                               mismatched = false
+                                                               result = build_client.read_lines do |l|
+                                                                       log.error(l, Log::LV_USER)
+                                                                       if l.include? "Password mismatched!" then
+                                                                               mismatched = true
+                                                                       end
+                                                               end
+=begin
+                                                               if result and not mismatched then
+                                                                       log.info("Friend Server #{ip}:#{port} upgrade failed!", Log::LV_USER)
+                                                               else
+                                                                       log.info("Friend Server #{ip}:#{port} upgrade requested!", Log::LV_USER)
+                                                               end
+=end
+                                                       end
+                       
+                                                       # terminate     
+                                                       build_client.terminate
+                                               end
+                                       end
+                               else
+                                       log.info("No Friend Server.", Log::LV_USER)
+                               end             
+
+                               # Start Build server
+                               cmd = Utils.execute_shell_generate("#{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.execute_shell_generate("#{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
+