Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 17:19:52 +0000 (02:19 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 17:19:52 +0000 (02:19 +0900)
356 files changed:
LICENSE.APLv2 [new file with mode: 0644]
NOTICE
README
build-cli
build-svr
dibs-web/Gemfile [new file with mode: 0644]
dibs-web/Gemfile.lock [new file with mode: 0644]
dibs-web/README.rdoc [new file with mode: 0644]
dibs-web/Rakefile [new file with mode: 0644]
dibs-web/app/assets/images/rails.png [new file with mode: 0644]
dibs-web/app/controllers/admin_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/admin_distribution_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/admin_group_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/admin_project_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/admin_server_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/admin_user_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/application_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/jobs_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/projects_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/sessions_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/users_controller.rb [new file with mode: 0644]
dibs-web/app/controllers/utils.rb [new file with mode: 0644]
dibs-web/app/helpers/admin_distribution_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/admin_group_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/admin_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/admin_project_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/admin_server_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/admin_user_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/application_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/jobs_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/projects_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/sessions_helper.rb [new file with mode: 0644]
dibs-web/app/helpers/users_helper.rb [new file with mode: 0644]
dibs-web/app/mailers/.gitkeep [new file with mode: 0644]
dibs-web/app/models/.gitkeep [new file with mode: 0644]
dibs-web/app/models/distribution.rb [new file with mode: 0644]
dibs-web/app/models/group.rb [new file with mode: 0644]
dibs-web/app/models/group_project_access.rb [new file with mode: 0644]
dibs-web/app/models/job.rb [new file with mode: 0644]
dibs-web/app/models/os_category.rb [new file with mode: 0644]
dibs-web/app/models/package.rb [new file with mode: 0644]
dibs-web/app/models/project.rb [new file with mode: 0644]
dibs-web/app/models/project_bin.rb [new file with mode: 0644]
dibs-web/app/models/project_git.rb [new file with mode: 0644]
dibs-web/app/models/project_os.rb [new file with mode: 0644]
dibs-web/app/models/remote_build_server.rb [new file with mode: 0644]
dibs-web/app/models/server_config.rb [new file with mode: 0644]
dibs-web/app/models/source.rb [new file with mode: 0644]
dibs-web/app/models/supported_os.rb [new file with mode: 0644]
dibs-web/app/models/sync_pkg_server.rb [new file with mode: 0644]
dibs-web/app/models/sync_project.rb [new file with mode: 0644]
dibs-web/app/models/user.rb [new file with mode: 0644]
dibs-web/app/models/user_group.rb [new file with mode: 0644]
dibs-web/config.ru [new file with mode: 0644]
dibs-web/config/application.rb [new file with mode: 0644]
dibs-web/config/boot.rb [new file with mode: 0644]
dibs-web/config/database.yml [new file with mode: 0644]
dibs-web/config/environment.rb [new file with mode: 0644]
dibs-web/config/environments/development.rb [new file with mode: 0644]
dibs-web/config/environments/production.rb [new file with mode: 0644]
dibs-web/config/environments/test.rb [new file with mode: 0644]
dibs-web/config/initializers/backtrace_silencers.rb [new file with mode: 0644]
dibs-web/config/initializers/inflections.rb [new file with mode: 0644]
dibs-web/config/initializers/mime_types.rb [new file with mode: 0644]
dibs-web/config/initializers/secret_token.rb [new file with mode: 0644]
dibs-web/config/initializers/session_store.rb [new file with mode: 0644]
dibs-web/config/initializers/wrap_parameters.rb [new file with mode: 0644]
dibs-web/config/locales/en.yml [new file with mode: 0644]
dibs-web/config/routes.rb [new file with mode: 0644]
dibs-web/db/schema.rb [new file with mode: 0644]
dibs-web/db/seeds.rb [new file with mode: 0644]
dibs-web/doc/README_FOR_APP [new file with mode: 0644]
dibs-web/public/.project [new file with mode: 0644]
dibs-web/public/404.html [new file with mode: 0644]
dibs-web/public/422.html [new file with mode: 0644]
dibs-web/public/500.html [new file with mode: 0644]
dibs-web/public/config.xml [new file with mode: 0644]
dibs-web/public/favicon.ico [new file with mode: 0644]
dibs-web/public/index.html [new file with mode: 0644]
dibs-web/public/javascripts/admin-distribution-add.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-distribution-modify.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-distribution.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-group-add.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-group-modify.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-group.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-project-add.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-project-modify.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-project.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-server-add.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-server-modify.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-server-remove.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-server.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-user-modify.js [new file with mode: 0644]
dibs-web/public/javascripts/admin-user.js [new file with mode: 0644]
dibs-web/public/javascripts/application.js [new file with mode: 0644]
dibs-web/public/javascripts/build.js [new file with mode: 0644]
dibs-web/public/javascripts/dibs-api.js [new file with mode: 0644]
dibs-web/public/javascripts/jobs.js [new file with mode: 0644]
dibs-web/public/javascripts/log.js [new file with mode: 0644]
dibs-web/public/javascripts/main.js [new file with mode: 0644]
dibs-web/public/javascripts/popup-window.js [new file with mode: 0644]
dibs-web/public/javascripts/post-process.js [new file with mode: 0644]
dibs-web/public/javascripts/projects.js [new file with mode: 0644]
dibs-web/public/javascripts/session.js [new file with mode: 0644]
dibs-web/public/javascripts/user.js [new file with mode: 0644]
dibs-web/public/log.html [new file with mode: 0644]
dibs-web/public/robots.txt [new file with mode: 0644]
dibs-web/public/stylesheets/application.css [new file with mode: 0644]
dibs-web/public/stylesheets/images/ajax-loader.gif [new file with mode: 0644]
dibs-web/public/stylesheets/images/ajax-loader.png [new file with mode: 0644]
dibs-web/public/stylesheets/images/icons-18-black.png [new file with mode: 0644]
dibs-web/public/stylesheets/images/icons-18-white.png [new file with mode: 0644]
dibs-web/public/stylesheets/images/icons-36-black.png [new file with mode: 0644]
dibs-web/public/stylesheets/images/icons-36-white.png [new file with mode: 0644]
dibs-web/public/upload.html [new file with mode: 0644]
dibs-web/script/rails [new file with mode: 0755]
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: 0755]
package/build.windows [new file with mode: 0755]
package/changelog [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/BuildJob.rb
src/build_server/BuildServer.rb
src/build_server/BuildServerController.rb
src/build_server/BuildServerException.rb [new file with mode: 0644]
src/build_server/BuildServerOptionParser.rb
src/build_server/CommonJob.rb [new file with mode: 0644]
src/build_server/CommonProject.rb [new file with mode: 0644]
src/build_server/DistributionManager.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 [new file with mode: 0644]
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 [new file with mode: 0644]
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/BuildComm.rb [new file with mode: 0644]
src/common/FileTransferViaDirect.rb [new file with mode: 0644]
src/common/FileTransferViaFTP.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/dependency.rb
src/common/execute_with_log.rb [new file with mode: 0755]
src/common/log.rb
src/common/mail.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 [new file with mode: 0644]
src/pkg_server/packageServerLog.rb
src/pkg_server/serverOptParser.rb
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-server.basic1/build-cli-01.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-02.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-03.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-03_1.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-04.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-05.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-06.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-07.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-08.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-09.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-10.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-11.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-12.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-12_1.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-13.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-14.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-15.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-16.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-17.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-18.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-19.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-20.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-21.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-22.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-23.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-24.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-25.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-26.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-27.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-28.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-29.testcase [new file with mode: 0644]
test/build-server.basic1/build-cli-30.testcase [new file with mode: 0644]
test/build-server.basic1/buildsvr.init [new file with mode: 0755]
test/build-server.basic1/pkgsvr.init [new file with mode: 0755]
test/build-server.basic1/testsuite [new file with mode: 0644]
test/build-server.basic2/build-svr-01.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-02.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-03.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-04.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-05.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-06.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-07.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-08.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-09.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-10.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-11.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-12.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-13.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-14.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-15.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-16.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-17.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-18.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-19.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-20.testcase [new file with mode: 0644]
test/build-server.basic2/build-svr-21.testcase [new file with mode: 0644]
test/build-server.basic2/testsuite [new file with mode: 0644]
test/build-server.multi-svr1/01.testcase [new file with mode: 0644]
test/build-server.multi-svr1/02.testcase [new file with mode: 0644]
test/build-server.multi-svr1/buildsvr1.init [new file with mode: 0755]
test/build-server.multi-svr1/buildsvr2.init [new file with mode: 0755]
test/build-server.multi-svr1/pkgsvr.init [new file with mode: 0755]
test/build-server.multi-svr1/testsuite [new file with mode: 0644]
test/build-server.multi-svr2/01.testcase [new file with mode: 0644]
test/build-server.multi-svr2/buildsvr.init [new file with mode: 0755]
test/build-server.multi-svr2/pkgsvr1.init [new file with mode: 0755]
test/build-server.multi-svr2/pkgsvr2.init [new file with mode: 0755]
test/build-server.multi-svr2/testsuite [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-01.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-02.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-03.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-04.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-05.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-06.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-07.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-08.testcase [new file with mode: 0644]
test/build-server.multi_dist1/build-svr2-09.testcase [new file with mode: 0644]
test/build-server.multi_dist1/testsuite [new file with mode: 0644]
test/build-server.multi_dist2/build-svr3-01.testcase [new file with mode: 0644]
test/build-server.multi_dist2/build-svr3-02.testcase [new file with mode: 0644]
test/build-server.multi_dist2/build-svr3-03.testcase [new file with mode: 0644]
test/build-server.multi_dist2/build-svr3-04.testcase [new file with mode: 0644]
test/build-server.multi_dist2/build-svr3-05.testcase [new file with mode: 0644]
test/build-server.multi_dist2/buildsvr.init [new file with mode: 0755]
test/build-server.multi_dist2/pkgsvr.init [new file with mode: 0755]
test/build-server.multi_dist2/testsuite [new file with mode: 0644]
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 [new file with mode: 0644]
test/packageserver01.testcase [new file with mode: 0644]
test/packageserver02.testcase [new file with mode: 0644]
test/packageserver03.testcase [new file with mode: 0644]
test/packageserver04.testcase [new file with mode: 0644]
test/packageserver05.testcase [new file with mode: 0644]
test/packageserver06.testcase [new file with mode: 0644]
test/packageserver07.testcase [new file with mode: 0644]
test/packageserver08.testcase [new file with mode: 0644]
test/packageserver09.testcase [new file with mode: 0644]
test/packageserver10.testcase [new file with mode: 0644]
test/packageserver11.testcase [new file with mode: 0644]
test/packageserver12.testcase [new file with mode: 0644]
test/packageserver13.testcase [new file with mode: 0644]
test/packageserver14.testcase [new file with mode: 0644]
test/packageserver15.testcase [new file with mode: 0644]
test/packageserver16.testcase [new file with mode: 0644]
test/packageserver17.testcase [new file with mode: 0644]
test/packageserver18.testcase [new file with mode: 0644]
test/packageserver19.testcase [new file with mode: 0644]
test/packageserver20.testcase [new file with mode: 0644]
test/packageserver21.testcase [new file with mode: 0644]
test/packageserver22.testcase [new file with mode: 0644]
test/packageserver23.testcase [new file with mode: 0644]
test/packageserver24.testcase [new file with mode: 0644]
test/packageserver25.testcase [new file with mode: 0644]
test/pkg-cli-checkupgrade.testcase [new file with mode: 0644]
test/pkg-cli-clean-f.testcase [new file with mode: 0644]
test/pkg-cli-download-t.testcase [new file with mode: 0644]
test/pkg-cli-download.testcase [new file with mode: 0644]
test/pkg-cli-install-f.testcase [new file with mode: 0644]
test/pkg-cli-install-t.testcase [new file with mode: 0644]
test/pkg-cli-install.testcase [new file with mode: 0644]
test/pkg-cli-installfile-f.testcase [new file with mode: 0644]
test/pkg-cli-installfile.testcase [new file with mode: 0644]
test/pkg-cli-listlpkg.testcase [new file with mode: 0644]
test/pkg-cli-listrpkg.testcase [new file with mode: 0644]
test/pkg-cli-showlpkg.testcase [new file with mode: 0644]
test/pkg-cli-showrpkg.testcase [new file with mode: 0644]
test/pkg-cli-source.testcase [new file with mode: 0644]
test/pkg-cli-uninstall-t.testcase [new file with mode: 0644]
test/pkg-cli-uninstall.testcase [new file with mode: 0644]
test/pkg-cli-update.testcase [new file with mode: 0644]
test/pkg-cli-upgrade.testcase [new file with mode: 0644]
test/pkg-cli.testsuite [new file with mode: 0644]
test/pkg-list
test/pkg-list-local [new file with mode: 0644]
test/pkginfo.manifest
test/pkgsvr2.init [new file with mode: 0755]
test/regression.rb [new file with mode: 0755]
test/test.sh [new file with mode: 0755]
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_linux.zip
test/upgrade/01.testcase [new file with mode: 0644]
test/upgrade/buildsvr1.init [new file with mode: 0755]
test/upgrade/buildsvr2.init [new file with mode: 0755]
test/upgrade/pkgsvr.init [new file with mode: 0755]
test/upgrade/testsuite [new file with mode: 0644]
tizen-ide/get_ide_sources.sh [new file with mode: 0755]
upgrade [new file with mode: 0755]

diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/NOTICE b/NOTICE
index 4297ee3350f479a5abf9f6237caa620814195c37..901a81c32e6740a31e39fe89db6f9579143c72d5 100644 (file)
--- a/NOTICE
+++ b/NOTICE
@@ -1 +1,3 @@
-Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE.APLv2 file for Apache License terms and conditions.
diff --git a/README b/README
index 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.
-    ## -o : Target OS(linux or windows)
+    ## -o : Target OS(ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64)
     ## -c : Clean build""
     ##      If set, start build after downloading all dependent packages
     ##      If not set, it will not download dependent packages if already downloaded
@@ -195,7 +195,7 @@ There are more useful commands provided
 You can list up available packages of server.
 
     ## pkg-cli list-rpkg [-o <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.
 
index 425c32a8fadf193bb246f8d291243528821bc5a8..fb9758e2be8d7efbad2e182a6795bd82ec67a559 100755 (executable)
--- a/build-cli
+++ b/build-cli
@@ -1,7 +1,7 @@
-#!/usr/bin/ruby -d
+#!/usr/bin/ruby
 
 =begin
+
  build-cli
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -35,75 +35,295 @@ $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/build_server"
 require "utils"
 require "BuildClientOptionParser"
 require "BuildComm"
+require "FileTransferViaFTP"
+require "FileTransferViaDirect"
+
 
-#option parsing 
-option = option_parse
-
-# if "--os" is not specified, use host os type
-if option[:os].nil? then 
-    option[:os] = Utils::HOST_OS
-else 
-    if not option[:os] =~ /^(linux|windows|darwin)$/ then 
-        puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS "
-        exit 1
-    end
+#option parsing
+begin
+       option = option_parse
+rescue => e
+       puts e.message
+       exit 0
 end
 
-if option[:domain].nil? then
-       option[:domain] = "172.21.17.46"
+
+# check HOST OS
+if not Utils.check_host_OS() then
+       puts "Error: Your host OS is not supported!"
+       exit 1
+end
+
+def query( ip, port, sym )
+       client = BuildCommClient.create( ip, port, nil, 0 )
+       if client.nil? then
+               puts "Connection to server failed!"
+               return nil
+       end
+       client.send "QUERY|#{sym.strip}"
+       result = client.receive_data()
+       if result.nil? then
+               puts "Error: #{client.get_error_msg()}"
+       end
+       client.terminate
+       return result
+end
+
+def query_system_info(ip, port)
+       # HOST SYSTEM INFO
+       puts "* SYSTEM INFO *"
+       data = query( ip, port, "SYSTEM")
+       if data.nil? then exit 1 end
+
+       result = data[0].split(",").map { |x| x.strip }
+       puts "HOST-OS: #{result[0]}"
+       puts "MAX_WORKING_JOBS: #{result[1]}"
+
+       # FTP INFO
+       puts "\n* FTP *"
+       data = query(ip, port, "FTP")
+       if data.nil? then exit 1 end
+
+       result = data[0].split(",").map { |x| x.strip }
+       puts "FTP_ADDR: #{result[0]}"
+       puts "FTP_USERNAME: #{result[1]}"
+
+       # SUPPORTED OS INFO
+       puts "\n* SUPPORTED OS LIST *"
+       data = query(ip, port, "OS")
+       if data.nil? then exit 1 end
+
+       data.each do |item|
+               puts "#{item.strip}"
+       end
+
+       # Friend lists
+       puts "\n* FRIEND SERVER LIST (WAIT|WORK/MAX) jobs [transfer count] *"
+       data = query(ip, port, "FRIEND")
+       if data.nil? then exit 1 end
+       i = 0
+       data.each do |item|
+               i = i + 1
+               info = item.split(",").map { |x| x.strip }
+               if info[0] == "DISCONNECTED" then
+                       puts "#{i}. #{info[0]}"
+               else
+                       puts "#{i}. #{info[0]} #{info[1]} server (#{info[2]}|#{info[3]}/#{info[4]}) [#{info[5]}]"
+               end
+       end
 end
 
-if option[:port].nil? then
-       option[:port] = 2222
+
+def query_project_list(ip, port)
+       puts "* PROJECT(S) *"
+       data = query( ip, port, "PROJECT")
+       data.each do |item|
+               tok = item.split(",").map { |x| x.strip }
+               type = (tok[0]=="G" ? "NORMAL":"REMOTE")
+               printf("%-25s %s %s\n",tok[1],type,tok[2])
+       end
+end
+
+
+def query_job_list(ip, port)
+       puts "* JOB(S) *"
+       data = query(ip, port, "JOB")
+       data.each do |item|
+               tok = item.split(",").map { |x| x.strip }
+               if tok[4].nil? then
+                       puts "#{tok[1]} #{tok[0]} #{tok[2]} #{tok[3]}"
+               else
+                       puts "#{tok[1]} #{tok[0]} #{tok[2]} (#{tok[3]}) #{tok[4]}"
+               end
+       end
+end
+
+
+# if "--os" is not specified, use pe
+if option[:os].nil? then
+       option[:os] = "default"
+end
+
+if option[:domain].nil? then
+       puts "Warn: Build server IP address is not specified. 127.0.0.1 will be used"
+       option[:domain] = "127.0.0.1"
 end
 
 begin
-       case option[:cmd] 
-       when "build" 
-               client = BuildCommClient.create( option[:domain], option[:port])
+       case option[:cmd]
+       when "build"
+               result = Utils.parse_server_addr(option[:domain])
+               if result.nil? then
+                       puts "Server address is incorrect. (#{option[:domain]})"
+                       puts "Tune as following format."
+                       puts " <ip>:<port>"
+                       exit 1
+               end
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
                if not client.nil? then
-                       client.send "BUILD,GIT,#{option[:git]},#{option[:commit]},#{option[:os]},,#{option[:async]}"
-                       client.print_stream
+                       client.send "BUILD|GIT|#{option[:project]}|#{option[:passwd]}|#{option[:os]}|#{option[:async]}|#{option[:noreverse]}|#{option[:dist]}|#{option[:user]}|#{option[:verbose]}"
+                       if not client.print_stream then
+                               puts "ERROR: #{client.get_error_msg()}"
+                       end
+
                        client.terminate
+               else
+                       puts "Connection to server failed!"
+                       exit 1
                end
        when "resolve"
-               client = BuildCommClient.create( option[:domain], option[:port])
-               if not client.nil? then
-                       client.send "RESOLVE,GIT,#{option[:git]},#{option[:commit]},#{option[:os]},,#{option[:async]}" 
-                       client.print_stream
-                       client.terminate
+               result = Utils.parse_server_addr(option[:domain])
+               if result.nil? then
+                       puts "Server address is incorrect. (#{option[:domain]})"
+                       puts "Tune as following format."
+                       puts " <ip>:<port>"
+                       exit 1
                end
-       when "query"
-               # SYSTEM INFO
-               client = BuildCommClient.create( option[:domain], option[:port])
+               client = BuildCommClient.create( result[0], result[1], nil, 0 )
                if not client.nil? then
-                       client.send "QUERY,SYSTEM" 
-                       result0 = client.receive_data()
-                       if result0.nil? then
-                               client.terminate
-                               exit(-1)
+                       client.send "RESOLVE|GIT|#{option[:project]}|#{option[:passwd]}|#{option[:os]}|#{option[:async]}|#{option[:dist]}|#{option[:user]}|#{option[:verbose]}"
+                       if not client.print_stream then
+                               puts "ERROR: #{client.get_error_msg()}"
                        end
-                       result0 = result0[0].split(",").map { |x| x.strip }
-                       puts "HOST-OS: #{result0[0]}"
-                       puts "MAX_WORKING_JOBS: #{result0[1]}"
                        client.terminate
                end
+       when "query"
+               result = Utils.parse_server_addr(option[:domain])
+               if result.nil? then
+                       puts "Server address is incorrect. (#{option[:domain]})"
+                       puts "Tune as following format."
+                       puts " <ip>:<port>"
+                       exit 1
+               end
 
-               # JOB INFO
-               client = BuildCommClient.create( option[:domain], option[:port])
-               if not client.nil? then
-                       client.send "QUERY,JOB"
-                       result1 = client.receive_data()
-                       if result0.nil? then
-                               client.terminate
-                               exit(-1)
+               query_system_info( result[0], result[1] )
+               puts ""
+               query_project_list( result[0], result[1])
+               puts ""
+               query_job_list( result[0], result[1])
+
+       when "query-system"
+               result = Utils.parse_server_addr(option[:domain])
+               if result.nil? then
+                       puts "Server address is incorrect. (#{option[:domain]})"
+                       puts "Tune as following format."
+                       puts " <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]}|#{option[:user]}"
+                               result1 = client.receive_data()
+                               if result1.nil? then
+                                       puts "Error: #{client.get_error_msg()}"
+                                       client.terminate
+                                       exit 1
+                               end
+                               puts result1
+                       else
+                               puts "Connection to server failed!"
+                               exit 1
                        end
-                       puts "* JOB *"
-                       for item in result1
-                               tok = item.split(",").map { |x| x.strip }
-                               puts "#{tok[1]} #{tok[0]} #{tok[2]}"    
+               else
+                       puts "you must input \"cancel job number\"!!"
+                       exit 1
+               end
+
+       when "register"
+               # check file exist
+               if not File.exist? option[:package] then
+                       puts "The file does not exist!.. #{option[:package]}"
+                       exit(-1)
+               end
+
+               result = Utils.parse_server_addr(option[:domain])
+               if result.nil? then
+                       puts "Server address is incorrect. (#{option[:domain]})"
+                       puts "Tune as following format."
+                       puts " <ip>:<port>"
+                       exit 1
+               end
+               bs_ip = result[0]
+               bs_port = result[1]
+
+               if not option[:fdomain].nil? then
+                       ftp_result = Utils.parse_ftpserver_url(option[:fdomain])
+                       if ftp_result.nil? or ftp_result.length != 4 then
+                               puts "FTP server url is incorrect. (#{option[:fdomain]})"
+                               puts "Tune as following format."
+                               puts " ftp://<usrename>:<passwd>@<address>"
+                               exit 1
                        end
+                       ip = ftp_result[0]
+                       port = ftp_result[1]
+                       username = ftp_result[2]
+                       passwd = ftp_result[3]
+                       transporter = FileTransferFTP.new( nil, ip, port, username, passwd )
+               else
+                       transporter = FileTransferDirect.new( nil )
+               end
+
+               # upload
+               client = BuildCommClient.create( bs_ip, bs_port, nil, 0 )
+               if client.nil? then
+                       puts "Can't access server #{bs_ip}:#{bs_port}"
+                       exit(-1)
+               end
+               dock = Utils.create_uniq_name()
+               msg = "UPLOAD|#{dock}"
+               client.send( msg )
+               result = client.send_file(option[:package], transporter)
+               client.terminate
+               if not result then
+                       puts "Uploading file failed!.. #{option[:package]}"
+                       exit(-1)
+               end
+
+               # register
+               client = BuildCommClient.create( bs_ip, bs_port, nil, 0 )
+               if client.nil? then
+                       puts "Can't access server #{bs_ip}:#{bs_port}"
+                       exit(-1)
+               end
+               client.send("REGISTER|BINARY|#{File.basename(option[:package])}|#{option[:passwd]}|#{dock}|#{option[:dist]}|#{option[:user]}|#{option[:noreverse]}")
+               if not client.print_stream then
+                       puts "ERROR: #{client.get_error_msg()}"
                end
+               client.terminate
 
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
index f1ddaf932c63084822146ee5f4568e29aa0de0ed..fc9a98f10e5e8de1d0ebd58a346283d32b0031e9 100755 (executable)
--- a/build-svr
+++ b/build-svr
@@ -1,7 +1,7 @@
-#!/usr/bin/ruby -d 
+#!/usr/bin/ruby
 
 =begin
+
  build-svr
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -32,70 +32,191 @@ require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 $LOAD_PATH.unshift File.dirname(__FILE__)+"/src/build_server"
 require "utils"
+require "log.rb"
 require "BuildServerOptionParser"
 require "BuildServerController"
 
-#option parsing 
+#option parsing
 begin
        option = option_parse
 rescue => e
-       puts "Option parse error"
        puts e.message
        exit 0
 end
 
-
-# if "--os" is not specified, use host os type
-if option[:os].nil? then
-    host_os = `uname -s`.strip
-    case host_os
-    when "Linux"
-        option[:os] = "linux"
-    when /MINGW32.*/
-        option[:os] = "windows"
-    when "Darwin"
-        option[:os] = "darwin"
-    else
-        if not option[:os] =~ /^(linux|windows|darwin)$/ then 
-            puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS "
-            exit 1
-        end
-    end 
-else
-    if not option[:os] =~ /^(linux|windows|darwin)$/ then 
-        puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS "
-        exit 1
-    end
-end 
-
-
+# check HOST OS
+if not Utils.check_host_OS() then
+       puts "Error: Your host OS is not supported!"
+       exit 1
+end
 
 begin
-       case option[:cmd] 
-       when "create" 
-               BuildServerController.create_server( option[:name], Utils::WORKING_DIR, option[:url], option[:domain], option[:pid] )
+       case option[:cmd]
+       when "create"
+               ftpsvr_addr = nil; ftpsvr_port = nil; ftpsvr_username = nil; ftpsvr_passwd = nil
+               if not option[:fdomain].nil? then
+                       ftp_result = Utils.parse_ftpserver_url(option[:fdomain])
+                       if ftp_result.nil? or ftp_result.length != 4 then
+                               puts "FTP server url is incorrect. (#{option[:fdomain]})"
+                               puts "Tune as following format."
+                               puts " ftp://<usrename>:<passwd>@<address>:<port>"
+                               exit 1
+                       end
+                       ftpsvr_addr = ftp_result[0]
+                       ftpsvr_port = ftp_result[1]
+                       ftpsvr_username = ftp_result[2]
+                       ftpsvr_passwd = ftp_result[3]
+               end
+               BuildServerController.create_server( option[:name], Utils::WORKING_DIR, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd )
        when "remove"
-               BuildServerController.remove_server( option[:name] ) 
+               BuildServerController.remove_server( option[:name] )
+       when "migrate"
+               BuildServerController.migrate_server( option[:name], option[:db_dsn], option[:db_user], option[:db_passwd] )
        when "start"
-               BuildServerController.start_server( option[:name], option[:port] ) 
-       when "build"
-               if not option[:git].nil? then
-                       if option[:resolve] then
-                               BuildServerController.resolve_git( option[:name], option[:git], option[:commit], option[:os], nil )
-                       else
-                               BuildServerController.build_git( option[:name], option[:git], option[:commit], option[:os], nil )
+               if( option[:child] ) then # Child Process
+                       BuildServerController.start_server( option[:name], option[:port] )
+               else  # Parent Process
+                       # check server config
+                       if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/server.cfg"
+                               raise RuntimeError, "The server \"#{option[:name]}\" does not exist!"
+                       end
+
+                       log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/main.log" )
+                       begin
+                               while(true)
+                                       log.info "Build Server[#{option[:name]}] Start - PORT:[#{option[:port]}]"
+                                       # Start child process
+                                       cmd = Utils.generate_shell_command("#{File.dirname(__FILE__)}/build-svr start -n #{option[:name]} -p #{option[:port]} --CHILD")
+                                       IO.popen(cmd)
+                                       pid = Process.wait
+
+                                       # End chlid process
+                                       log.info "Child process terminated, pid = #{pid}, status = #{$?.exitstatus}"
+                                       if ($?.exitstatus == 0) then # SERVER STOP COMMAND
+                                               log.info "Down Build Server."
+                                               break
+                                       elsif ($?.exitstatus == 99) then # DIBS UPGRADE
+                                               cmd = "#{File.dirname(__FILE__)}/upgrade -l #{File.dirname(__FILE__)} -S -t BUILDSERVER -n #{option[:name]} -p #{option[:port]}"
+                                               if File.exist? "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist" then
+                                                       File.open("#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist","r") do |f|
+                                                               f.each_line do |l|
+                                                                       cmd += " -D #{l.strip}"
+                                                                       break
+                                                               end
+                                                       end
+                                                       File.delete "#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist"
+                                               end
+
+                                               cmd = Utils.generate_shell_command(cmd)
+                                               puts cmd
+                                               Utils.spawn(cmd)
+                                               log.info cmd
+                                               log.info "Down Build Server for DIBS upgrade."
+                                               break
+                                       else
+                                               log.error "Down Build Server. Try reboot Build Server."
+                                       end
+                               end
+                       rescue => e
+                               log.error( e.message, Log::LV_USER)
                        end
-               elsif not option[:local].nil? then
-                       if option[:resolve] then
-                               BuildServerController.resolve_local( option[:name], option[:local], option[:os], nil )
+               end
+       when "stop"
+               BuildServerController.stop_server( option[:name] )
+
+       when "upgrade"
+               if not (option[:dist].nil? or option[:dist].empty?) then
+                       build_server = BuildServerController.get_server(option[:name])
+                       # distribution check
+                       if not build_server.distmgr.get_distribution(option[:dist]).nil? then
+                               File.open("#{BuildServer::CONFIG_ROOT}/#{option[:name]}/upgrade_dist","w") do |f|
+                                       f.puts option[:dist]
+                               end
                        else
-                               BuildServerController.build_local( option[:name], option[:local], option[:os], nil )
+                               puts "Distribution \"#{option[:dist]}\" is not exits"
+                               puts "Upgrade Failed!!"
+                               exit 1
                        end
+               end
+
+               BuildServerController.upgrade_server( option[:name] )
+
+       when "add-svr"
+               svr_result = Utils.parse_server_addr(option[:domain])
+               if svr_result.nil? or svr_result.length != 2 then
+                       puts "Server address is incorrect. Tune as following format."
+                       puts " <ip>:<port>"
+                       exit 1
+               end
+               pkgsvr_addr = svr_result[0]
+               pkgsvr_port = svr_result[1]
+               BuildServerController.add_remote_server( option[:name], pkgsvr_addr, pkgsvr_port )
+
+       when "remove-svr"
+               BuildServerController.remove_remote_server( option[:name], pkgsvr_addr, pkgsvr_port )
+
+       when "add-os"
+               BuildServerController.add_target_os( option[:name], option[:os] )
+
+       when "remove-os"
+               BuildServerController.remove_target_os( option[:name], option[:os] )
+
+       when "add-dist"
+               svr_result = Utils.parse_server_addr(option[:domain])
+               if svr_result.nil? or svr_result.length != 2 then
+                       puts "Server address is incorrect. (#{option[:domain]})"
+                       puts "Tune as following format."
+                       puts " <ip>:<port>"
+                       exit 1
+               end
+               pkgsvr_url = option[:url]
+               pkgsvr_addr = svr_result[0]
+               pkgsvr_port = svr_result[1]
+               BuildServerController.add_distribution( option[:name], option[:dist], pkgsvr_url, pkgsvr_addr, pkgsvr_port )
+
+       when "remove-dist"
+               BuildServerController.remove_distribution( option[:name], option[:dist] )
+
+       when "lock-dist"
+               BuildServerController.lock_distribution( option[:name], option[:dist] )
+
+       when "unlock-dist"
+               BuildServerController.unlock_distribution( option[:name], option[:dist] )
+
+       when "add-sync"
+               BuildServerController.add_sync_package_server( option[:name], option[:url], option[:dist] )
+
+       when "remove-sync"
+               BuildServerController.remove_sync_package_server( option[:name], option[:url], option[:dist] )
+
+       when "add-prj"
+               if not option[:git].nil? then
+                       BuildServerController.add_project( option[:name], option[:pid],
+                                                                                         option[:git], option[:branch], option[:remote], option[:passwd],
+                                                                                         option[:os], option[:dist] )
                else
-                       RuntimeError "Wrong build options are specified!"
+                       BuildServerController.add_binary_project( option[:name], option[:pid],
+                                                                                                        option[:package], option[:passwd], option[:os], option[:dist] )
                end
-       when "add"
-               BuildServerController.add_friend_server( option[:name], option[:domain], option[:port] ) 
+
+       when "remove-prj"
+               BuildServerController.remove_project( option[:name], option[:pid], option[:dist] )
+
+       when "fullbuild"
+               BuildServerController.build_all_projects( option[:name], option[:dist] )
+
+       when "register"
+               BuildServerController.register_package( option[:name], option[:package], option[:dist] )
+
+       when "query"
+               BuildServerController.query_server( option[:name] )
+
+       when "set-attr"
+               BuildServerController.set_server_attribute( option[:name], option[:attr], option[:value] )
+
+       when "get-attr"
+               BuildServerController.get_server_attribute( option[:name], option[:attr] )
+
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
diff --git a/dibs-web/Gemfile b/dibs-web/Gemfile
new file mode 100644 (file)
index 0000000..cfe9b05
--- /dev/null
@@ -0,0 +1,50 @@
+source 'https://rubygems.org'
+
+gem 'rails', '3.2.8'
+
+# Bundle edge Rails instead:
+# gem 'rails', :git => 'git://github.com/rails/rails.git'
+
+gem 'sqlite3'
+
+gem 'json'
+
+gem 'execjs'
+
+# Gems used only for assets and not required
+# in production environments by default.
+group :assets do
+  gem 'sass-rails',   '~> 3.2.3'
+  gem 'coffee-rails', '~> 3.2.1'
+
+  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
+  # gem 'therubyracer', :platforms => :ruby
+
+  gem 'uglifier', '>= 1.0.3'
+end
+
+gem 'jquery-rails'
+
+# mysql
+gem 'mysql2', '> 0.3' # as stated above
+
+# user
+gem 'builder'
+
+# For encrypt password
+gem "bcrypt-ruby", :require => "bcrypt"
+
+# To use ActiveModel has_secure_password
+# gem 'bcrypt-ruby', '~> 3.0.0'
+
+# To use Jbuilder templates for JSON
+# gem 'jbuilder'
+
+# Use unicorn as the app server
+# gem 'unicorn'
+
+# Deploy with Capistrano
+# gem 'capistrano'
+
+# To use debugger
+# gem 'ruby-debug'
diff --git a/dibs-web/Gemfile.lock b/dibs-web/Gemfile.lock
new file mode 100644 (file)
index 0000000..d4f7f1a
--- /dev/null
@@ -0,0 +1,118 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    actionmailer (3.2.8)
+      actionpack (= 3.2.8)
+      mail (~> 2.4.4)
+    actionpack (3.2.8)
+      activemodel (= 3.2.8)
+      activesupport (= 3.2.8)
+      builder (~> 3.0.0)
+      erubis (~> 2.7.0)
+      journey (~> 1.0.4)
+      rack (~> 1.4.0)
+      rack-cache (~> 1.2)
+      rack-test (~> 0.6.1)
+      sprockets (~> 2.1.3)
+    activemodel (3.2.8)
+      activesupport (= 3.2.8)
+      builder (~> 3.0.0)
+    activerecord (3.2.8)
+      activemodel (= 3.2.8)
+      activesupport (= 3.2.8)
+      arel (~> 3.0.2)
+      tzinfo (~> 0.3.29)
+    activeresource (3.2.8)
+      activemodel (= 3.2.8)
+      activesupport (= 3.2.8)
+    activesupport (3.2.8)
+      i18n (~> 0.6)
+      multi_json (~> 1.0)
+    arel (3.0.2)
+    bcrypt-ruby (3.0.1)
+    builder (3.0.3)
+    coffee-rails (3.2.2)
+      coffee-script (>= 2.2.0)
+      railties (~> 3.2.0)
+    coffee-script (2.2.0)
+      coffee-script-source
+      execjs
+    coffee-script-source (1.3.3)
+    erubis (2.7.0)
+    execjs (1.4.0)
+      multi_json (~> 1.0)
+    hike (1.2.1)
+    i18n (0.6.1)
+    journey (1.0.4)
+    jquery-rails (2.1.3)
+      railties (>= 3.1.0, < 5.0)
+      thor (~> 0.14)
+    json (1.7.5)
+    mail (2.4.4)
+      i18n (>= 0.4.0)
+      mime-types (~> 1.16)
+      treetop (~> 1.4.8)
+    mime-types (1.19)
+    multi_json (1.3.6)
+    mysql2 (0.3.11)
+    polyglot (0.3.3)
+    rack (1.4.1)
+    rack-cache (1.2)
+      rack (>= 0.4)
+    rack-ssl (1.3.2)
+      rack
+    rack-test (0.6.2)
+      rack (>= 1.0)
+    rails (3.2.8)
+      actionmailer (= 3.2.8)
+      actionpack (= 3.2.8)
+      activerecord (= 3.2.8)
+      activeresource (= 3.2.8)
+      activesupport (= 3.2.8)
+      bundler (~> 1.0)
+      railties (= 3.2.8)
+    railties (3.2.8)
+      actionpack (= 3.2.8)
+      activesupport (= 3.2.8)
+      rack-ssl (~> 1.3.2)
+      rake (>= 0.8.7)
+      rdoc (~> 3.4)
+      thor (>= 0.14.6, < 2.0)
+    rake (0.9.2.2)
+    rdoc (3.12)
+      json (~> 1.4)
+    sass (3.2.1)
+    sass-rails (3.2.5)
+      railties (~> 3.2.0)
+      sass (>= 3.1.10)
+      tilt (~> 1.3)
+    sprockets (2.1.3)
+      hike (~> 1.2)
+      rack (~> 1.0)
+      tilt (~> 1.1, != 1.3.0)
+    sqlite3 (1.3.6)
+    thor (0.16.0)
+    tilt (1.3.3)
+    treetop (1.4.10)
+      polyglot
+      polyglot (>= 0.3.1)
+    tzinfo (0.3.33)
+    uglifier (1.3.0)
+      execjs (>= 0.3.0)
+      multi_json (~> 1.0, >= 1.0.2)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  bcrypt-ruby
+  builder
+  coffee-rails (~> 3.2.1)
+  execjs
+  jquery-rails
+  json
+  mysql2 (> 0.3)
+  rails (= 3.2.8)
+  sass-rails (~> 3.2.3)
+  sqlite3
+  uglifier (>= 1.0.3)
diff --git a/dibs-web/README.rdoc b/dibs-web/README.rdoc
new file mode 100644 (file)
index 0000000..7c36f23
--- /dev/null
@@ -0,0 +1,261 @@
+== Welcome to Rails
+
+Rails is a web-application framework that includes everything needed to create
+database-backed web applications according to the Model-View-Control pattern.
+
+This pattern splits the view (also called the presentation) into "dumb"
+templates that are primarily responsible for inserting pre-built data in between
+HTML tags. The model contains the "smart" domain objects (such as Account,
+Product, Person, Post) that holds all the business logic and knows how to
+persist themselves to a database. The controller handles the incoming requests
+(such as Save New Account, Update Product, Show Post) by manipulating the model
+and directing data to the view.
+
+In Rails, the model is handled by what's called an object-relational mapping
+layer entitled Active Record. This layer allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in
+link:files/vendor/rails/activerecord/README.html.
+
+The controller and view are handled by the Action Pack, which handles both
+layers by its two parts: Action View and Action Controller. These two layers
+are bundled in a single package due to their heavy interdependence. This is
+unlike the relationship between the Active Record and Action Pack that is much
+more separate. Each of these packages can be used independently outside of
+Rails. You can read more about Action Pack in
+link:files/vendor/rails/actionpack/README.html.
+
+
+== Getting Started
+
+1. At the command prompt, create a new Rails application:
+       <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
+
+2. Change directory to <tt>myapp</tt> and start the web server:
+       <tt>cd myapp; rails server</tt> (run with --help for options)
+
+3. Go to http://localhost:3000/ and you'll see:
+       "Welcome aboard: You're riding Ruby on Rails!"
+
+4. Follow the guidelines to start developing your application. You can find
+the following resources handy:
+
+* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
+* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
+
+
+== Debugging Rails
+
+Sometimes your application goes wrong. Fortunately there are a lot of tools that
+will help you debug it and get it back on the rails.
+
+First area to check is the application log files. Have "tail -f" commands
+running on the server.log and development.log. Rails will automatically display
+debugging and runtime information to these files. Debugging info will also be
+shown in the browser on requests from 127.0.0.1.
+
+You can also log your own messages directly into the log file from your code
+using the Ruby logger class from inside your controllers. Example:
+
+  class WeblogController < ActionController::Base
+    def destroy
+      @weblog = Weblog.find(params[:id])
+      @weblog.destroy
+      logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
+    end
+  end
+
+The result will be a message in your log file along the lines of:
+
+  Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
+
+More information on how to use the logger is at http://www.ruby-doc.org/core/
+
+Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
+several books available online as well:
+
+* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
+* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
+
+These two books will bring you up to speed on the Ruby language and also on
+programming in general.
+
+
+== Debugger
+
+Debugger support is available through the debugger command when you start your
+Mongrel or WEBrick server with --debugger. This means that you can break out of
+execution at any point in the code, investigate and change the model, and then,
+resume execution! You need to install ruby-debug to run the server in debugging
+mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
+
+  class WeblogController < ActionController::Base
+    def index
+      @posts = Post.all
+      debugger
+    end
+  end
+
+So the controller will accept the action, run the first line, then present you
+with a IRB prompt in the server window. Here you can do things like:
+
+  >> @posts.inspect
+  => "[#<Post:0x14a6be8
+          @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
+       #<Post:0x14a6620
+          @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
+  >> @posts.first.title = "hello from a debugger"
+  => "hello from a debugger"
+
+...and even better, you can examine how your runtime objects actually work:
+
+  >> f = @posts.first
+  => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
+  >> f.
+  Display all 152 possibilities? (y or n)
+
+Finally, when you're ready to resume execution, you can enter "cont".
+
+
+== Console
+
+The console is a Ruby shell, which allows you to interact with your
+application's domain model. Here you'll have all parts of the application
+configured, just like it is when the application is running. You can inspect
+domain models, change values, and save to the database. Starting the script
+without arguments will launch it in the development environment.
+
+To start the console, run <tt>rails console</tt> from the application
+directory.
+
+Options:
+
+* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
+  made to the database.
+* Passing an environment name as an argument will load the corresponding
+  environment. Example: <tt>rails console production</tt>.
+
+To reload your controllers and models after launching the console run
+<tt>reload!</tt>
+
+More information about irb can be found at:
+link:http://www.rubycentral.org/pickaxe/irb.html
+
+
+== dbconsole
+
+You can go to the command line of your database directly through <tt>rails
+dbconsole</tt>. You would be connected to the database with the credentials
+defined in database.yml. Starting the script without arguments will connect you
+to the development database. Passing an argument will connect you to a different
+database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
+PostgreSQL and SQLite 3.
+
+== Description of Contents
+
+The default directory structure of a generated Ruby on Rails application:
+
+  |-- app
+  |   |-- assets
+  |       |-- images
+  |       |-- javascripts
+  |       `-- stylesheets
+  |   |-- controllers
+  |   |-- helpers
+  |   |-- mailers
+  |   |-- models
+  |   `-- views
+  |       `-- layouts
+  |-- config
+  |   |-- environments
+  |   |-- initializers
+  |   `-- locales
+  |-- db
+  |-- doc
+  |-- lib
+  |   `-- tasks
+  |-- log
+  |-- public
+  |-- script
+  |-- test
+  |   |-- fixtures
+  |   |-- functional
+  |   |-- integration
+  |   |-- performance
+  |   `-- unit
+  |-- tmp
+  |   |-- cache
+  |   |-- pids
+  |   |-- sessions
+  |   `-- sockets
+  `-- vendor
+      |-- assets
+          `-- stylesheets
+      `-- plugins
+
+app
+  Holds all the code that's specific to this particular application.
+
+app/assets
+  Contains subdirectories for images, stylesheets, and JavaScript files.
+
+app/controllers
+  Holds controllers that should be named like weblogs_controller.rb for
+  automated URL mapping. All controllers should descend from
+  ApplicationController which itself descends from ActionController::Base.
+
+app/models
+  Holds models that should be named like post.rb. Models descend from
+  ActiveRecord::Base by default.
+
+app/views
+  Holds the template files for the view that should be named like
+  weblogs/index.html.erb for the WeblogsController#index action. All views use
+  eRuby syntax by default.
+
+app/views/layouts
+  Holds the template files for layouts to be used with views. This models the
+  common header/footer method of wrapping views. In your views, define a layout
+  using the <tt>layout :default</tt> and create a file named default.html.erb.
+  Inside default.html.erb, call <% yield %> to render the view using this
+  layout.
+
+app/helpers
+  Holds view helpers that should be named like weblogs_helper.rb. These are
+  generated for you automatically when using generators for controllers.
+  Helpers can be used to wrap functionality for your views into methods.
+
+config
+  Configuration files for the Rails environment, the routing map, the database,
+  and other dependencies.
+
+db
+  Contains the database schema in schema.rb. db/migrate contains all the
+  sequence of Migrations for your schema.
+
+doc
+  This directory is where your application documentation will be stored when
+  generated using <tt>rake doc:app</tt>
+
+lib
+  Application specific libraries. Basically, any kind of custom code that
+  doesn't belong under controllers, models, or helpers. This directory is in
+  the load path.
+
+public
+  The directory available for the web server. Also contains the dispatchers and the
+  default HTML files. This should be set as the DOCUMENT_ROOT of your web
+  server.
+
+script
+  Helper scripts for automation and generation.
+
+test
+  Unit and functional tests along with fixtures. When using the rails generate
+  command, template test files will be generated for you and placed in this
+  directory.
+
+vendor
+  External libraries that the application depends on. Also includes the plugins
+  subdirectory. If the app has frozen rails, those gems also go here, under
+  vendor/rails/. This directory is in the load path.
diff --git a/dibs-web/Rakefile b/dibs-web/Rakefile
new file mode 100644 (file)
index 0000000..f818fd1
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Dibs::Application.load_tasks
diff --git a/dibs-web/app/assets/images/rails.png b/dibs-web/app/assets/images/rails.png
new file mode 100644 (file)
index 0000000..d5edc04
Binary files /dev/null and b/dibs-web/app/assets/images/rails.png differ
diff --git a/dibs-web/app/controllers/admin_controller.rb b/dibs-web/app/controllers/admin_controller.rb
new file mode 100644 (file)
index 0000000..b2803d5
--- /dev/null
@@ -0,0 +1,79 @@
+=begin 
+ admin_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 AdminController < ApplicationController
+
+       before_filter :check_login_status, :check_admin_group
+
+       def queryAllOS
+               os_list = SupportedOs.all(:order => "name")
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       doc.Data {
+                               if not os_list.nil? 
+                                       os_list.each do |os|
+                                               doc.OS {
+                                                       doc.OsName(os.name)
+                                                       category = OsCategory.find(:first, :conditions => ["id = ?", os.os_category_id]) 
+                                                       if not category.nil?
+                                                               doc.OsCategory(category.name)
+                                                       end
+                                               }
+                                       end
+                               end
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def queryAllOSCategory
+               os_category_list = OsCategory.all(:order => "name")
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       doc.Data {
+                               if not os_category_list.nil? 
+                                       os_category_list.each do |category|
+                                               doc.OsCategoryName(category.name)
+                                       end
+                               end
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+end
diff --git a/dibs-web/app/controllers/admin_distribution_controller.rb b/dibs-web/app/controllers/admin_distribution_controller.rb
new file mode 100644 (file)
index 0000000..6d838c6
--- /dev/null
@@ -0,0 +1,261 @@
+=begin 
+ admin_distribution_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 AdminDistributionController < ApplicationController
+
+       before_filter :check_login_status, :check_admin_group
+
+       def queryAllDistribution
+               # get full distribution list
+               distributions = Distribution.all
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       #generate to XML
+                       doc.Data {
+                               if not distributions.nil? 
+                                       distributions.each do |distribution|
+                                               doc.DistributionName(distribution.name)
+                                       end
+                               end
+                       }
+               }
+               
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def queryDistributionInfo
+               dist_name = params[:distribution]
+
+               if dist_name.nil? or dist_name.empty? 
+                       render :text => "Distribution name is empty", :content_type => "text/xml", :status => 406
+                       return
+               end
+
+               # get distribution 
+               distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               if distribution.nil? 
+                       render :text => "Can't find distribution : #{dist_name}", :content_type => "text/xml", :status => 406
+                       return
+               end
+
+               # get sync package server 
+               sync_package_server = SyncPkgServer.find(:first, :conditions => ["distribution_id = ?", distribution.id])
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       #generate to XML
+                       doc.Data{
+                               doc.DistributionInfo{
+                                       doc.DistributionName(distribution.name)
+                                       doc.PackageServerUrl(distribution.pkgsvr_url)
+                                       doc.PackageServerAddress(distribution.pkgsvr_addr)
+                                       doc.Status(distribution.status)
+                                       doc.Description(distribution.description)
+                               }
+
+                               doc.SyncPackageServer{
+                                       if sync_package_server.nil?
+                                               doc.Url("")
+                                               doc.Period("")
+                                               doc.Description("")
+                                       else
+                                               doc.Url(sync_package_server.pkgsvr_url)
+                                               doc.Period(sync_package_server.period)
+                                               doc.Description(sync_package_server.description)
+                                       end
+                               }
+                       }
+               }
+               
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def addDistribution
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               dist_name = change_item[:DistributionName]
+               if dist_name.nil? or dist_name.empty? then
+                       errmsg = "Can't find [#{dist_name}] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               dist = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               if dist.nil?
+                       dist = Distribution.new
+                       dist.name = change_item[:DistributionName]
+                       dist.pkgsvr_url = change_item[:URL]
+                       dist.pkgsvr_addr = change_item[:Address]
+                       dist.status = change_item[:DistStatus]
+                       dist.description = change_item[:Description]
+                       dist.save
+
+                       sync_pkg_svr = SyncPkgServer.new
+                       sync_pkg_svr.distribution_id = dist.id
+                       sync_pkg_svr.pkgsvr_url = change_item[:SyncPkgSvrUrl]
+                       sync_pkg_svr.period = change_item[:SyncPkgSvrPeriod]
+                       sync_pkg_svr.description = change_item[:SyncPkgSvrDescription]
+                       sync_pkg_svr.save
+               else
+                       errmsg = "Distribution[#{dist_name}] already exist"
+               end
+
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :json => { :error=> errmsg }, :status => 406
+               end
+       end
+
+       def removeDistribution
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               dist_name = change_item[:DistributionName]
+               if dist_name.nil? or dist_name.empty? then
+                       errmsg = "Can't find [#{dist_name}] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               dist = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               if dist.nil?
+                       errmsg = "Distribution[#{dist_name}] not exist"
+               else
+                       # first, remove sync package server
+                       sync_pkg_svr = SyncPkgServer.find(:first, :conditions => ["distribution_id = ?", dist.id])
+
+                       if not sync_pkg_svr.nil?
+                               sync_pkg_svr.destroy
+                       end
+
+                       # remove distribution
+                       dist.destroy
+               end
+
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :json => { :error=> errmsg }, :status => 406
+               end
+       end
+
+       def modifyDistribution
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               dist_name = change_item[:DistributionName]
+               if dist_name.nil? or dist_name.empty? then
+                       errmsg = "Can't find [#{dist_name}] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               dist = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               if dist.nil?
+                       errmsg = "Distribution[#{dist_name}] not exist"
+               else
+                       dist.pkgsvr_url = change_item[:URL]
+                       dist.pkgsvr_addr = change_item[:Address]
+                       dist.status = change_item[:DistStatus]
+                       dist.description = change_item[:Description]
+                       dist.save
+
+                       sync_pkg_svr_url = change_item[:SyncPkgSvrUrl]
+                       sync_pkg_svr_period = change_item[:SyncPkgSvrPeriod]
+                       sync_pkg_svr_description = change_item[:SyncPkgSvrDescription]
+                       sync_pkg_svr = SyncPkgServer.find(:first, :conditions => ["distribution_id = ?", dist.id])
+                       if not sync_pkg_svr_url.nil? and not sync_pkg_svr_url.empty?
+                               if sync_pkg_svr.nil?
+                                       sync_pkg_svr = SyncPkgServer.new        
+                               end
+                               sync_pkg_svr.distribution_id = dist.id
+                               sync_pkg_svr.pkgsvr_url = sync_pkg_svr_url
+                               sync_pkg_svr.period = sync_pkg_svr_period
+                               sync_pkg_svr.description = sync_pkg_svr_description
+                               sync_pkg_svr.save
+                       elsif not sync_pkg_svr.nil? and not sync_pkg_svr_url.nil? and sync_pkg_svr_url.empty?
+                               # if sync_pkg_svr is already exist and modified sync_pkg_svr_url is empty then remove it
+                               sync_pkg_svr.destroy
+                       end
+               end
+
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :json => { :error=> errmsg }, :status => 406
+               end
+       end
+
+       def fullBuildDistribution
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               dist_name = change_item[:DistributionName]
+               if dist_name.nil? or dist_name.empty? then
+                       errmsg = "Can't find [#{dist_name}] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               dist = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               if dist.nil?
+                       errmsg = "Distribution[#{dist_name}] not exist"
+               end
+
+               server_config = Server_config.find(:first, :conditions => ["property = \"id\""])
+               if server_config.nil? 
+                       errmsg = "Server name can't find"
+               else
+                       server_name = server_config.value
+
+                       if server_name.nil? or server_name.empty?
+                               errmsg = "Server name can't find"
+                       end
+               end
+
+               if errmsg.empty?
+                       Utils.sbi_fullbuild_command(server_name, dist_name)
+                       render :json => { :success => "OK!" }
+               else
+                       render :json => { :error=> errmsg }, :status => 406
+               end
+       end
+end
diff --git a/dibs-web/app/controllers/admin_group_controller.rb b/dibs-web/app/controllers/admin_group_controller.rb
new file mode 100644 (file)
index 0000000..5818e1b
--- /dev/null
@@ -0,0 +1,240 @@
+=begin 
+ admin_group_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 AdminGroupController < ApplicationController
+
+       before_filter :check_login_status, :check_admin_group
+       skip_before_filter :check_admin_group, :only => [:queryAllGroup]
+
+       def queryAllGroup
+               project_list = Project.all(:order => "name")
+               group_list = Group.all
+            
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       doc.Data {
+                               if not group_list.nil? 
+                                       group_list.each do |group|
+                                               group_access_list = GroupProjectAccess.find(:all, :conditions => ["group_id = ?", group.id])
+                    
+                                               doc.Group {
+                                                       doc.GroupName(group.name)
+                                                       doc.AdminFlag(group.admin)
+                                                       doc.Description(group.description)
+
+                                                       if not group_access_list.nil? 
+                                                               group_access_list.each do |group_right|
+                                                                       project = Project.find(:first, :conditions => ["id = ?", group_right.project_id]);
+                                                                       distribution = Distribution.find(:first, :conditions => ["id = ?", project.distribution_id]);
+                                                                       if not project.nil?
+                                                                               doc.AccessableProject {
+                                                                                       doc.ProjectName(project.name)
+                                                                                       doc.ProjectDistribution(distribution.name)
+                                                                               }
+                                                                       end
+                                                               end
+                                                       end
+                                               }
+                                       end
+                               end
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def queryGroupInfo
+               group_name = params[:groupName]
+               if group_name.nil? or group_name.empty? 
+                       render :text => "Group name is empty", :content_type => "text/xml", :status => 406
+                       return
+               end
+
+               group = Group.find(:first, :conditions => ["name = ?", group_name])
+               if group.nil? 
+                       render :text => "Can't find group : #{group_name}", :content_type => "text/xml", :status => 406
+                       return
+               end
+
+               project_list = Project.all(:order => "name")
+
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               if not project_list.nil?
+                                       project_list.each do |project|
+                                               distribution = Distribution.find(:first, :conditions => ["id = ?", project.distribution_id]);
+                                               doc.Project{
+                                                       doc.Name(project.name)
+                                                       doc.Id(project.id)
+                                                       doc.DistName(distribution.name)
+                                               }
+                                       end
+                               end
+            
+                               doc.Group {
+                                       doc.Name(group.name)
+                                       
+                                       group_access_list = GroupProjectAccess.find(:all, :conditions => ["group_id = ?", group.id])
+                    
+                                       if not group_access_list.nil? and not group_access_list.empty? 
+                                               project_id_list = []
+                                               group_access_list.each do |group_right|
+                                                       project_id_list.push group_right.project_id
+                                               end
+            
+                                               doc.ProjectList(project_id_list.join(","))
+                                       end
+                               }
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def modifyGroup
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               group_name = change_item[:GroupName]
+               if group_name.nil? or group_name.empty?
+                       render :text => "Group name is invalid", :status => 406
+                       return
+               else
+                       group = Group.find(:first, :conditions => ["name= ?", group_name])
+               end
+               
+               if group.nil?
+                       errmsg = "Can't find group"
+               else
+                       new_group_name = change_item[:NewGroupName]
+                       admin_flag = change_item[:AdminFlag]
+                       description = change_item[:Description]
+                       project_id_list = change_item[:ProjectList].split(",")
+            
+                       group.name = new_group_name
+                       group.admin = admin_flag
+                       group.description = description
+                       group.save
+            
+                       GroupProjectAccess.delete_all(["group_id = ?", group.id])
+
+                       project_id_list.each do |project_id|
+                               item = GroupProjectAccess.new 
+                               item.group_id = group.id
+                               item.project_id = project_id
+                               item.build = "TRUE"
+                               item.save
+                       end
+               end
+               
+               
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :text => errmsg, :status => 406
+               end
+       end
+
+       def removeGroup
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               group_name = change_item[:GroupName]
+               if group_name.nil? or group_name.empty?
+                       render :text => "Group name is invalid", :status => 406
+                       return
+               else
+                       group = Group.find(:first, :conditions => ["name= ?", group_name])
+               end
+               
+               if group.nil?
+                       errmsg = "Can't find group"
+               else
+                       user_group = UserGroup.find(:first, :conditions => ["group_id = ?", group.id])
+                       if user_group.nil?
+                               GroupProjectAccess.delete_all(["group_id = ?", group.id])
+                               group.destroy
+                       else
+                               errmsg = "Can't remove. #{group_name} has users."
+                       end
+               end
+               
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :text => errmsg, :status => 406
+               end
+       end
+
+       def addGroup
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               group_name = change_item[:GroupName]
+               if group_name.nil? or group_name.empty?
+                       render :text => "Group name is invalid", :status => 406
+                       return
+               else
+                       group = Group.find(:first, :conditions => ["name= ?", group_name])
+               end
+               
+               if not group.nil?
+                       errmsg = "Group already exist"
+               else
+                       group = Group.new
+                       group.name = group_name
+                       group.admin = change_item[:AdminFlag]
+                       group.description = change_item[:Description]
+                       group.save
+            
+                       project_id_list = change_item[:ProjectList].split(",")
+                       project_id_list.each do |project_id|
+                               group_project_access = GroupProjectAccess.new
+                               group_project_access.group_id = group.id
+                               group_project_access.project_id = project_id
+                               group_project_access.save
+                       end
+               end
+
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :text => errmsg, :status => 406
+               end
+       end
+end
diff --git a/dibs-web/app/controllers/admin_project_controller.rb b/dibs-web/app/controllers/admin_project_controller.rb
new file mode 100644 (file)
index 0000000..a0f7b72
--- /dev/null
@@ -0,0 +1,301 @@
+=begin 
+ admin_project_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 AdminProjectController < ApplicationController
+       def queryAllProject
+               project_list = Project.all(:order => "name")
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       doc.Data {
+                               if not project_list.nil? 
+                                       project_list.each do |project|
+                                       distribution = Distribution.find(:first, :conditions => ["id = ?", project.distribution_id]);
+                                               doc.Project{
+                                                       doc.Name(project.name)
+                                                       doc.Id(project.id)
+                                                       doc.DistName(distribution.name)
+                                               }
+                                       end
+                               end
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def queryProjectsInDistributionForAdmin
+               dist_name = params[:distribution]
+
+               if dist_name.nil? or dist_name.empty? 
+                       render :text => "Distribution name is empty", :content_type => "text/xml", :status => 406
+                       return
+               end
+
+               # get distribution 
+               distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               if distribution.nil? 
+                       render :text => "Can't find distribution : #{dist_name}", :content_type => "text/xml", :status => 406
+                       return
+               end
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+
+                       #generate to XML
+                       doc.Data{
+                               project_list = Project.find_by_sql("SELECT projects.id
+                                                                                                            , projects.name 
+                                                                                                            , projects.ptype
+                                                                                                         FROM projects
+                                                                                                                , distributions
+                                                                                                        WHERE distributions.name = \"#{dist_name}\"
+                                                                                                          AND distributions.id = projects.distribution_id 
+                                                                                                        ORDER BY projects.name")
+                               if not project_list.nil?
+                                       project_list.each do |project|
+                                               doc.Project {
+                                                       doc.ProjectName(project.name)
+                                                       doc.Type(project.ptype)
+            
+                                                       os_list = ProjectOs.find(:all, :conditions => ["project_id = ?", project.id])
+                                                       if not os_list.nil? then
+                                                               os_list.each do |os|
+                                                                       supported_os = SupportedOs.find(:first, :conditions => ["id = ?", os.supported_os_id])
+                                                                       doc.OS(supported_os.name)
+                                                               end
+                                                       end
+
+                                                       case project.ptype.upcase
+                                                       when "GIT"
+                                                               git = ProjectGit.find(:first, :conditions => ["project_id = ?", project.id])
+                                                               if not git.nil? then
+                                                                       doc.GitRepos(git.git_repos)
+                                                                       doc.GitBranch(git.git_branch)
+                                                               end
+                    
+                                                       when "BINARY"
+                                                               bin = ProjectBin.find(:first, :conditions => ["project_id = ?", project.id])
+                                                               if not bin.nil? then
+                                                                       doc.PackageName(bin.pkg_name)
+                                                               end
+                                                       end
+                                               }
+                                       end
+                               end
+                       }
+               }
+               
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def addProject
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               project_name = change_item[:Name]
+               project_type = change_item[:ProjectType].upcase
+               project_dist_name = change_item[:Distribution]
+               project_password = change_item[:ProjectPass]
+
+               if project_name.nil? or project_name.empty? then
+                       errmsg = "Can't find [Name] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               distribution = Distribution.find(:first, :conditions => ["name = ?", project_dist_name])
+               project = Project.find(:first, :conditions => ["name = ? and distribution_id = ? and ptype = ?", project_name, distribution.id, project_type])
+
+               if not project.nil? 
+                       errmsg = "project already exist"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               if not project_type.eql? "GIT" and not project_type.eql? "BINARY"
+                       errmsg = "project type is invalid"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               project = Project.new
+               project.name = project_name
+               project.ptype = project_type
+               project.password = project_password
+               project.distribution_id = distribution.id
+               #TODO: set project user is admin. admin user id is '1'
+               project.user_id = 1
+               project.save
+
+               if not change_item[:OSNameList].nil?
+                       os_name_list = change_item[:OSNameList].split(",")
+                       os_name_list.each do |os_name|
+                               supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name])
+                               #need check not found
+                               project_os = ProjectOs.new
+                               project_os.project_id = project.id
+                               project_os.supported_os_id = supported_os.id
+                               project_os.save
+                       end
+               end
+
+               case project.ptype
+               when "GIT"
+                       git = ProjectGit.new
+                       git.project_id = project.id
+                       git.git_repos = change_item[:Address]
+                       git.git_branch = change_item[:Branch]
+                       git.save
+               when "BINARY"
+                       binary = ProjectBin.new
+                       binary.project_id = project.id
+                       binary.pkg_name = change_item[:PackageName]
+                       binary.save
+               end
+
+               render :json => { :success => "OK!" }
+       end
+
+       def removeProject
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               if change_item[:Name].nil? or change_item[:Name].empty? then
+                       errmsg = "Can't find [Name] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               dist_name = change_item[:Distribution]
+               project_name = change_item[:Name]
+               project_type = change_item[:ProjectType]
+               distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               project = Project.find(:first, :conditions => ["name = ? and distribution_id = ?", project_name, distribution.id])
+
+               if project.nil? 
+                       errmsg = "project does not exist"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               case project_type.upcase
+               when "GIT"
+                       ProjectGit.delete_all(["project_id = ?", project.id])
+                       ProjectOs.delete_all(["project_id = ?", project.id])
+                       GroupProjectAccess.delete_all(["project_id = ?", project.id])
+               when "BINARY"
+                       ProjectBin.delete_all(["project_id = ?", project.id])
+                       GroupProjectAccess.delete_all(["project_id = ?", project.id])
+               else
+                       errmsg = "project type is invalid"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # remove project os 
+               ProjectOs.delete_all(["project_id = ?", project.id])
+
+               # remove project 
+               project.destroy
+
+               render :json => { :success => "OK!" }
+       end
+
+       def modifyProject
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+               
+               dist_name = change_item[:Distribution]
+               old_project_name = change_item[:Name]
+               project_type = change_item[:ProjectType].upcase
+
+               if old_project_name.nil? or old_project_name.empty? then
+                       errmsg = "Can't find [#{old_project_name}] information"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               if not project_type.eql? "GIT" and not project_type.eql? "BINARY"
+                       errmsg = "project type is invalid"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               project = Project.find(:first, :conditions => ["name = ? and distribution_id = ? and ptype = ?", old_project_name, distribution.id, project_type])
+               project.name = change_item[:NewProjectName]
+               project.password = change_item[:ProjectPass]
+
+               # remove project os and reset project os
+               ProjectOs.delete_all(["project_id = ?", project.id])
+               if not change_item[:OSNameList].nil?
+                       os_name_list = change_item[:OSNameList].split(",")
+                       os_name_list.each do |os_name|
+                               supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name])
+                               #need check not found
+                               project_os = ProjectOs.new
+                               project_os.project_id = project.id
+                               project_os.supported_os_id = supported_os.id
+                               project_os.save
+                       end
+               end
+
+               case project_type
+               when "GIT"
+                       project_git = ProjectGit.find(:first, :conditions => ["project_id = ?", project.id])
+                       if project_git.nil?
+                               project_git.project_id = project.id
+                               project_git = ProjectGit.new
+                       end
+                       project_git.git_repos = change_item[:ProjectAddress]
+                       project_git.git_branch = change_item[:ProjectBranch]
+                       project_git.save
+
+               when "BINARY"
+                       project_bin = ProjectBin.find(:first, :conditions => ["project_id = ?", project.id])
+                       if project_bin.nil?
+                               project_bin = ProjectBin.new
+                               project_bin.project_id = project.id
+                       end
+                       project_bin.pkg_name = change_item[:PackageName]
+                       project_bin.save
+               end
+
+               project.save
+               render :json => { :success => "OK!" }
+       end
+end
diff --git a/dibs-web/app/controllers/admin_server_controller.rb b/dibs-web/app/controllers/admin_server_controller.rb
new file mode 100644 (file)
index 0000000..8efb20d
--- /dev/null
@@ -0,0 +1,424 @@
+=begin 
+ admin_server_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 AdminServerController < ApplicationController
+       def queryAllServer
+               # get full distribution list
+               server_config = Server_config.all
+               remote_build_servers = RemoteBuildServer.all
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+        
+                       #generate to XML
+                       doc.Data {
+                               if not server_config.nil? 
+                                       server_config.each do |info|
+                                               doc.ServerConfig {
+                                                       doc.Property( info.property )
+                                                       doc.Value( info.value )
+                                               }
+                                       end
+                               end
+
+                               if not remote_build_servers.nil? 
+                                       remote_build_servers.each do |server|
+                                               doc.RemoteBuildServer {
+                                                       doc.Address(server.svr_addr)
+                                                       supported_os = SupportedOs.find(:first, :conditions => ["id = ?", server.supported_os_id])
+                                                       if supported_os.nil?
+                                                               doc.SupportedOS("")
+                                                       else
+                                                               doc.SupportedOS(supported_os.name)
+                                                       end
+                                                       doc.Status(server.status)
+                                                       doc.MaxJobCount(server.max_job_count)
+                                                       doc.WorkingJobCount(server.working_job_count)
+                                                       doc.WaitingJobCount(server.waiting_job_count)
+                                                       doc.Description(server.description)
+                                               }
+                                       end
+                               end
+                       }
+               }
+               
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def addRemoteBuildServer
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               address = change_item[:Address]
+               description = change_item[:Description]
+               if address.nil? or address.empty? 
+                       errmsg = "Server address is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", address])
+        
+               if server.nil? 
+                       server = RemoteBuildServer.new
+                       server.svr_addr = address
+                       server.description = description 
+                       server.save
+
+                       render :json => { :success => "OK!" }
+               else
+                       errmsg = "Server already exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               end
+       end
+
+       def modifyRemoteBuildServer
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               address = change_item[:Address]
+               if address.nil? or address.empty? 
+                       errmsg = "Server address is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", address])
+
+               if server.nil? 
+                       errmsg = "Server does not exist"
+               else
+                       new_address = change_item[:NewAddress]
+                       description = change_item[:Description]
+                       
+                       # error check for server already exist
+                       if not address.eql? new_address
+                               new_server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", new_address])
+                               
+                               if not new_server.nil?
+                                       errmsg = "Server already exist"
+                               end
+                       end
+
+                       server.svr_addr = new_address
+                       server.description = description
+                       server.save
+               end
+               
+
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :json => { :error => errmsg }, :status => 406
+               end
+       end
+
+       def removeRemoteBuildServer
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               address = change_item[:Address]
+               if address.nil? or address.empty? 
+                       errmsg = "Server address is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               server = RemoteBuildServer.find(:first, :conditions => ["svr_addr = ?", address])
+        
+               if server.nil? 
+                       errmsg = "Server does not exist"
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       server.destroy
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def addOsCategory
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               name = change_item[:Name]
+               if name.nil? or name.empty? 
+                       errmsg = "Os category name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               osCategory = OsCategory.find(:first, :conditions => ["name = ?", name])
+        
+               if osCategory.nil? 
+                       osCategory= OsCategory.new
+                       osCategory.name = name 
+                       osCategory.save
+
+                       render :json => { :success => "OK!" }
+               else
+                       errmsg = "Os category already exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               end
+       end
+
+       def removeOsCategory
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               name = change_item[:Name]
+               if name.nil? or name.empty? 
+                       errmsg = "Os category name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               osCategory = OsCategory.find(:first, :conditions => ["name = ?", name])
+        
+               if osCategory.nil? 
+                       errmsg = "Can't find os category"
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       osCategory.destroy
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def addSupportedOS
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               os_name = change_item[:Name]
+               category_name = change_item[:OsCategory]
+               if os_name.nil? or os_name.empty? 
+                       errmsg = "Os name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+               if category_name.nil? or category_name.empty? 
+                       errmsg = "Os category is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               os_category = OsCategory.find(:first, :conditions => ["name = ?", category_name])
+               supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name])
+        
+               if os_category.nil? 
+                       errmsg = "Os category does not exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               elsif not supported_os.nil?
+                       errmsg = "supported os already exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       supported_os = SupportedOs.new
+                       supported_os.name = os_name 
+                       supported_os.os_category_id = os_category.id
+                       supported_os.save
+
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def removeSupportedOS
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               os_name = change_item[:Name]
+               if os_name.nil? or os_name.empty? 
+                       errmsg = "Os name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name])
+        
+               if supported_os.nil?
+                       errmsg = "supported os does not exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       supported_os.destroy
+
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def modifySupportedOS
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               os_name = change_item[:Name]
+               new_os_name = change_item[:NewName]
+               category_name = change_item[:OsCategory]
+               if os_name.nil? or os_name.empty? 
+                       errmsg = "Os name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               os_category = OsCategory.find(:first, :conditions => ["name = ?", category_name])
+               supported_os = SupportedOs.find(:first, :conditions => ["name = ?", os_name])
+        
+               if os_category.nil? 
+                       errmsg = "Os category does not exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               elsif supported_os.nil?
+                       errmsg = "supported os does not exist"
+
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       if not os_name.eql? new_os_name
+                               new_supported_os = SupportedOs.find(:first, :conditions => ["name = ?", new_os_name])
+                               if new_supported_os.nil?
+                                       supported_os.name = new_os_name 
+                               else
+                                       errmsg = "supported os already exist"
+                    
+                                       render :json => { :error => errmsg }, :status => 406
+                                       return
+                               end
+                       end
+
+                       supported_os.os_category_id = os_category.id
+                       supported_os.save
+
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def addServerInfo
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               property = change_item[:Property]
+               value = change_item[:Value]
+               if property.nil? or property.empty? 
+                       errmsg = "Property name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+               if value.nil? or value.empty? 
+                       errmsg = "Value is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               config = Server_config.find(:first, :conditions => ["property = ?", property])
+        
+               if not config.nil? 
+                       errmsg = "Config alerady exist"
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       config = Server_config.new
+                       config.property = property
+                       config.value = value
+                       config.save
+
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def modifyServerInfo
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               property = change_item[:Property]
+               value = change_item[:Value]
+               if property.nil? or property.empty? 
+                       errmsg = "Property is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+               if value.nil? or value.empty? 
+                       errmsg = "Value is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               config = Server_config.find(:first, :conditions => ["property = ?", property])
+        
+               if config.nil? 
+                       errmsg = "Config does not exist"
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       config.value = value
+                       config.save
+
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+       def removeServerInfo
+               change_group_list = params[:ChangeInfoList]
+               change_item = change_group_list[0]
+               errmsg = ""
+
+               property = change_item[:Property]
+               if property.nil? or property.empty? 
+                       errmsg = "Property is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               # get server for error check
+               config = Server_config.find(:first, :conditions => ["property = ?", property])
+        
+               if config.nil? 
+                       errmsg = "Property does not exist"
+                       render :json => { :error => errmsg }, :status => 406
+               else
+                       config.destroy
+                       render :json => { :success => "OK!" }
+               end
+       end
+
+end
diff --git a/dibs-web/app/controllers/admin_user_controller.rb b/dibs-web/app/controllers/admin_user_controller.rb
new file mode 100644 (file)
index 0000000..7f4af7e
--- /dev/null
@@ -0,0 +1,142 @@
+=begin 
+ admin_user_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 AdminUserController < ApplicationController
+
+       before_filter :check_login_status, :check_admin_group
+
+       def queryAllUser
+               user_list = User.all(:order => "name")
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+               
+                       doc.Data {
+                               if not user_list.nil? 
+                                       user_list.each do |user|
+                                               doc.User {
+                                                       doc.Name(user.name)
+                                                       doc.Email(user.email)
+                                                       doc.GroupList {
+                                                               group_list = Group.find_by_sql("SELECT groups.name
+                                                                                                                                       , groups.admin
+                                                                                                                                       , groups.description
+                                                                                                                               FROM users
+                                                                                                                               , user_groups
+                                                                                                                               , groups
+                                                                                                                               WHERE users.id = user_groups.user_id
+                                                                                                                       AND user_groups.group_id = groups.id
+                                                                                                                               AND users.email = \"#{user.email}\"")
+                                                               group_list.each { |group|
+                                                                               doc.GroupName(group.name)
+                                                               }
+                                                       }
+                                               }
+                                       end
+                               end
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def modifyUser
+               change_user_list = params[:ChangeInfoList]
+               change_item = change_user_list[0]
+               errmsg = ""
+
+               email = change_item[:Email]
+               group_name = change_item[:GroupName]
+               user_name = change_item[:UserName]
+
+               if email.nil? or email.empty?
+                       render :text => "Email is invalid", :status => 406
+                       return
+               else
+                       user = User.find(:first, :conditions => ["email = ?", email])
+
+                       if user.nil? 
+                               errmsg = "Can't find user information"
+                               render :text => errmsg, :status => 406
+                               return
+                       end
+               end
+
+               if group_name.nil? or group_name.empty?
+                       render :text => "Group name is invalid", :status => 406
+                       return
+               else
+                       group = Group.find(:first, :conditions => ["name = ?", group_name])
+                       if group.nil? 
+                               errmsg = "Can't find group information"
+                               render :text => errmsg, :status => 406
+                               return
+                       end
+               end
+
+               user.name  = user_name
+               user.save
+
+               UserGroup.delete_all(["user_id = ?", user.id])
+
+               user_groups = UserGroup.new
+
+               user_groups.user_id = user.id
+               user_groups.group_id = group.id
+               user_groups.status = "ACTIVE"
+               user_groups.save
+
+               render :json => { :success => "OK!" }
+       end
+
+       def removeUser
+               change_user_list = params[:ChangeInfoList]
+               change_item = change_user_list[0]
+               errmsg = ""
+
+               email = change_item[:Email]
+               if email.nil? or email.empty?
+                       render :text => "Email is invalid", :status => 406
+                       return
+               else
+                       user = User.find(:first, :conditions => ["email = ?", email])
+               end
+
+               if user.nil?
+                       errmsg = "Can't find user information"
+                       render :text => errmsg, :status => 406
+               else
+                       UserGroup.delete_all(["user_id = ?", user.id])
+
+                       user.destroy
+                       render :json => { :success => "OK!" }
+               end
+       end
+end
diff --git a/dibs-web/app/controllers/application_controller.rb b/dibs-web/app/controllers/application_controller.rb
new file mode 100644 (file)
index 0000000..1ad4921
--- /dev/null
@@ -0,0 +1,162 @@
+=begin 
+ application_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 ApplicationController < ActionController::Base
+       #protect_from_forgery
+
+       JOBS_STAUTS_WAITING = "WAITING"
+
+       helper_method :current_user
+       
+       def get_user_id
+               if @current_user.nil?
+                       current_user
+               end
+
+               if not @current_user.nil?
+                       return @current_user.id
+               else
+                       return nil
+               end
+       end
+
+       def get_user_email
+               if @current_user.nil?
+                       current_user
+               end
+
+               if not @current_user.nil?
+                       return @current_user.email
+               else
+                       return nil
+               end
+       end
+
+       def get_group_list(email)
+               if not email.nil?
+                       group_list = Group.find_by_sql("SELECT groups.id
+                                                                                               , groups.name
+                                                                                               , groups.admin
+                                                                                               , groups.description
+                                                                                       FROM users
+                                                                                       , user_groups
+                                                                                       , groups
+                                                                                       WHERE users.id = user_groups.user_id
+                                                                               AND user_groups.group_id = groups.id
+                                                                                       AND users.email = \"#{email}\"")
+                       return group_list
+               else
+                       return nil
+               end
+       end
+
+       def is_admin(email)
+               if not email.nil?
+                       group = Group.find_by_sql("SELECT count(*) AS cnt
+                                                                               FROM users
+                                                                               , user_groups
+                                                                               , groups
+                                                                               WHERE users.id = user_groups.user_id
+                                                                       AND user_groups.group_id = groups.id
+                                                                       AND groups.admin = 'TRUE'
+                                                                               AND users.email = \"#{email}\"")
+                       if group[0].cnt > 0
+                               return TRUE
+                       end
+               end
+
+               return FALSE
+       end
+
+    def generate_xml_header(doc)
+               email = get_user_email
+               group_list = get_group_list(email)
+               if is_admin(email)
+                       admin = "TRUE"
+               else
+                       admin = "FALSE"
+               end
+             
+               doc.Header {
+                       doc.UserInfo {
+                               doc.Email(email)
+                               doc.Name(@current_user.name)
+                               doc.Admin(admin)
+                               doc.GroupList {
+                                       group_list.each { |group|
+                                               doc.Group {
+                                                       doc.GroupName(group.name)
+                                                       doc.GroupAdmin(group.admin)
+                                                       doc.GroupDescription(group.description)
+                                               }
+                                       }
+                               }
+                       }
+               }
+    end
+
+       private
+       def current_user
+               @current_user ||= User.find(:first, :conditions => {:email => session[:user_email]}) if session[:user_email]
+       end
+
+       def check_login_status
+               if session[:user_email].nil? then
+                       render :nothing => true, :status => 401
+                       return
+               end
+       end
+
+       def check_admin_group
+               if session[:user_email].nil? or session[:user_email].empty? then
+                       render :nothing => true, :status => 401
+                       return false
+               else
+                       admin = "FALSE"
+                       user_email = session[:user_email]
+
+                       user = User.find(:first, :conditions => ["email = ?", user_email])
+
+                       group_list = get_group_list(user.email)
+
+                       group_list.each {|group|
+                               if group.admin == "TRUE"
+                                       admin = "TRUE"
+                                       break;
+                               end
+                       }
+
+                       if user.nil? or admin != "TRUE"
+                               render :nothing => true, :status => 401
+                               return false
+                       end
+               end
+
+               return true
+       end
+end
diff --git a/dibs-web/app/controllers/jobs_controller.rb b/dibs-web/app/controllers/jobs_controller.rb
new file mode 100644 (file)
index 0000000..b4f3797
--- /dev/null
@@ -0,0 +1,634 @@
+=begin 
+ jobs_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 JobsController < ApplicationController
+
+       before_filter :check_login_status
+
+       QUERY_CNT = 30
+
+       def list
+       end
+
+       def listAll
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               listQuery(doc, "QUERY", params[:distribution], params[:status], params[:lastID], "", "")
+                       }
+               }
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def listSearchUser
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               listQuery(doc, "QUERY", params[:distribution], params[:status], params[:lastID], params[:user], "")
+                       }
+               }
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def listSearchGroup
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               listQueryGroup(doc, "QUERY", params[:distribution], params[:status], params[:lastID], params[:group])
+                       }
+               }
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def listSearchProject
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               listQueryProject(doc, "QUERY", params[:distribution], params[:status], params[:lastID], params[:project])
+                       }
+               }
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def listSearchDate
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               listQuery(doc, "QUERY", params[:distribution], params[:status], params[:lastID], "", params[:date])
+                       }
+               }
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def updateList
+               condition = params[:Condition]
+               param = params[:Param]
+               distribution = params[:Distribution]
+               status = params[:Status]
+               latest_id = params[:LatestId]
+               working_job_list = params[:WorkingJobId]
+
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               #new job list
+                               case condition
+                                       when "all"
+                                               listQuery(doc, "UPDATE", distribution, status, latest_id, "", "")
+                                       when "user"
+                                               listQuery(doc, "UPDATE", distribution, status, latest_id, param, "")
+                                       when "group"
+                                               listQueryGroup(doc, "UPDATE", distribution, status, latest_id, param)
+                                       when "project"
+                                               listQueryProject(doc, "UPDATE", distribution, status, latest_id, param)
+                                       when "date"
+                                               listQuery(doc, "UPDATE", distribution, status, latest_id, "", param)
+                                       else
+                               end
+
+                               # working job list for update
+                               doc.WorkingJobList {
+                                       if not working_job_list.nil?
+                                               working_job_list.each do |job_id|
+                                                       job = get_job_info(job_id)
+                                                       doc.Job {
+                                                               doc.Id(job.job_id)
+                                                               doc.Distribution(job.distribution_name)
+                                                               doc.ProjectName(job.project_name)
+                                                               doc.JobType(job.job_type)
+                                                               doc.JobAttribute(job.job_attribute)
+                                                               doc.ParentJobId(job.parent_job_id)
+                                                               doc.Os(job.supported_os_name)
+                                                               doc.Status(job.status)
+                                                               doc.UserName(job.user_name)
+                                                               doc.StartTime(job.start_time)
+                                                               doc.EndTime(job.end_time)
+                                                       }
+
+                                                       if job.job_attribute == "MULTI"
+                                                               child_jobs = get_child_job_info(job.job_id)
+                                                               child_jobs.each {|job|
+                                                                       doc.Job {
+                                                                               doc.Id(job.job_id)
+                                                                               doc.Distribution(job.distribution_name)
+                                                                               doc.ProjectName(job.project_name)
+                                                                               doc.JobType(job.job_type)
+                                                                               doc.JobAttribute("CHILD")
+                                                                               doc.ParentJobId(job.parent_job_id)
+                                                                               doc.Os(job.supported_os_name)
+                                                                               doc.Status(job.status)
+                                                                               doc.UserName(job.user_name)
+                                                                               doc.StartTime(job.start_time)
+                                                                               doc.EndTime(job.end_time)
+                                                                       }
+                                                               }
+                                                       end
+                                               end
+                                       end
+                               }
+                       }
+               }
+
+               render :text => out_string, :content_type => "text/xml"
+
+       end
+
+       def listQuery(doc, query_type, distribution, status, last_id, user, date)
+               condition = ""
+
+               if(distribution == "ALL")
+                       distribution = "%"
+               end
+
+               if(status == "ALL")
+                       status = "'FINISHED', 'JUST_CREATED', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING', 'ERROR', 'CANCELED'"
+               elsif(status == "SUCCESS")
+                       status = "'FINISHED'"
+               elsif(status == "WORKING")
+                       status = "'JUST_CREATE', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING'"
+               elsif(status == "ERROR")
+                       status = "'ERROR', 'CANCELED'"
+               end
+
+               if(query_type == "QUERY")
+                       if(last_id == "LATEST")
+                               last_job_id = Job.maximum(:id)
+                               if last_job_id.nil?
+                                       last_job_id = 0
+                               end
+                       else
+                               last_job_id = last_id.to_i - 1
+                       end
+                       condition = "jobs.id <= #{last_job_id}"
+               else
+                       condition = "jobs.id > #{last_id}"
+               end
+
+               user = user + "%"
+
+               date = date + "%"
+
+               jobs = Job.find_by_sql("SELECT jobs.id
+                                                                        , CASE WHEN jobs.jtype like 'MULTI%' THEN 'MULTI'
+                                                                                        ELSE 'SINGLE' END AS job_attribute
+                                                                FROM jobs 
+                                                                LEFT JOIN projects 
+                                                                  ON jobs.project_id = projects.id
+                                                                LEFT JOIN users
+                                                                  ON jobs.user_id = users.id
+                                                                LEFT JOIN supported_os
+                                                                  ON jobs.supported_os_id = supported_os.id
+                                                                LEFT JOIN distributions
+                                                                  ON jobs.distribution_id = distributions.id
+                                                                LEFT JOIN remote_build_servers
+                                                                  ON jobs.remote_build_server_id = remote_build_servers.id
+                                                                LEFT JOIN sources
+                                                                  ON jobs.source_id = sources.id
+                                                         WHERE #{condition}
+                                                               AND jobs.parent_job_id IS NULL
+                                                               AND jobs.status in (#{status})
+                                                               AND users.name like '#{user}'
+                                                               AND distributions.name like '#{distribution}'
+                                                               AND DATE(jobs.start_time) like '#{date}'
+                                                         ORDER BY jobs.id DESC
+                                                         LIMIT #{QUERY_CNT}")
+
+               #generate to XML
+               doc.JobList {
+                       jobs.each {|job_list|
+                               job = get_job_info(job_list.id)
+
+                               doc.Job {
+                                       doc.Id(job.job_id)
+                                       doc.Distribution(job.distribution_name)
+                                       doc.ProjectName(job.project_name)
+                                       doc.JobType(job.job_type)
+                                       doc.JobAttribute(job_list.job_attribute)
+                                       doc.ParentJobId(job.parent_job_id)
+                                       doc.Os(job.supported_os_name)
+                                       doc.Status(job.status)
+                                       doc.UserName(job.user_name)
+                                       doc.StartTime(job.start_time)
+                                       doc.EndTime(job.end_time)
+                               }
+
+                               if job_list.job_attribute == "MULTI"
+                                       child_jobs = get_child_job_info(job.job_id)
+                                       child_jobs.each {|job|
+                                               doc.Job {
+                                                       doc.Id(job.job_id)
+                                                       doc.Distribution(job.distribution_name)
+                                                       doc.ProjectName(job.project_name)
+                                                       doc.JobType(job.job_type)
+                                                       doc.JobAttribute("CHILD")
+                                                       doc.Os(job.supported_os_name)
+                                                       doc.Status(job.status)
+                                                       doc.UserName(job.user_name)
+                                                       doc.StartTime(job.start_time)
+                                                       doc.EndTime(job.end_time)
+                                               }
+                                       }
+                               end
+                       }
+               }
+       end
+
+       def listQueryGroup(doc, query_type, distribution, status, last_id, group)
+
+               if(distribution == "ALL")
+                       distribution = "%"
+               end
+
+               if(status == "ALL")
+                       status = "'FINISHED', 'JUST_CREATED', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING', 'ERROR', 'CANCELED'"
+               elsif(status == "SUCCESS")
+                       status = "'FINISHED'"
+               elsif(status == "WORKING")
+                       status = "'JUST_CREATE', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING'"
+               elsif(status == "ERROR")
+                       status = "'ERROR', 'CANCELED'"
+               end
+
+               if(query_type == "QUERY")
+                       if(last_id == "LATEST")
+                               last_job_id = Job.maximum(:id)
+                               if last_job_id.nil?
+                                       last_job_id = 0
+                               end
+                       else
+                               last_job_id = last_id.to_i - 1
+                       end
+                       condition = "jobs.id <= #{last_job_id}"
+               else
+                       condition = "jobs.id > #{last_id}"
+               end
+
+               group = group + "%"
+
+               jobs = Job.find_by_sql("SELECT jobs.id
+                                                                        , CASE WHEN jobs.jtype like 'MULTI%' THEN 'MULTI'
+                                                                                        ELSE 'SINGLE' END AS job_attribute
+                                                                FROM jobs 
+                                                                LEFT JOIN distributions ON jobs.distribution_id = distributions.id 
+                                                                 WHERE #{condition}
+                                                                       AND jobs.parent_job_id IS NULL
+                                                                       AND distributions.name like '#{distribution}'
+                                                                       AND jobs.status in (#{status})
+                                                                       AND jobs.user_id IN (SELECT users.id
+                                                                                                                 FROM users
+                                                                                                                 LEFT JOIN user_groups ON user_groups.user_id = users.id
+                                                                                                                 LEFT JOIN groups ON groups.id = user_groups.group_id
+                                                                                                                WHERE groups.name LIKE '#{group}')
+                                                                 ORDER BY jobs.id DESC
+                                                                 LIMIT #{QUERY_CNT}")
+
+               #generate to XML
+               doc.Data {
+                       doc.JobList {
+                               jobs.each {|job_list|
+                                       job = get_job_info(job_list.id)
+
+                                       doc.Job {
+                                               doc.Id(job.job_id)
+                                               doc.Distribution(job.distribution_name)
+                                               doc.ProjectName(job.project_name)
+                                               doc.JobType(job.job_type)
+                                               doc.JobAttribute(job_list.job_attribute)
+                                               doc.ParentJobId(job.parent_job_id)
+                                               doc.Os(job.supported_os_name)
+                                               doc.Status(job.status)
+                                               doc.UserName(job.user_name)
+                                               doc.StartTime(job.start_time)
+                                               doc.EndTime(job.end_time)
+                                       }
+
+                                       if job_list.job_attribute == "MULTI"
+                                               child_jobs = get_child_job_info(job.job_id)
+                                               child_jobs.each {|job|
+                                                       doc.Job {
+                                                               doc.Id(job.job_id)
+                                                               doc.Distribution(job.distribution_name)
+                                                               doc.ProjectName(job.project_name)
+                                                               doc.JobType(job.job_type)
+                                                               doc.JobAttribute("CHILD")
+                                                               doc.Os(job.supported_os_name)
+                                                               doc.Status(job.status)
+                                                               doc.UserName(job.user_name)
+                                                               doc.StartTime(job.start_time)
+                                                               doc.EndTime(job.end_time)
+                                                       }
+                                               }
+                                       end
+                               }
+                       }
+               }
+       end
+
+       def listQueryProject(doc, query_type, distribution, status, last_id, project)
+               if(distribution == "ALL")
+                       distribution = "%"
+               end
+
+               if(status == "ALL")
+                       status = "'FINISHED', 'JUST_CREATED', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING', 'ERROR', 'CANCELED'"
+               elsif(status == "SUCCESS")
+                       status = "'FINISHED'"
+               elsif(status == "WORKING")
+                       status = "'JUST_CREATE', 'WAITING', 'WORKING', 'REMOTE_WORKING', 'PENDING'"
+               elsif(status == "ERROR")
+                       status = "'ERROR', 'CANCELED'"
+               end
+
+               if(query_type == "QUERY")
+                       if(last_id == "LATEST")
+                               last_job_id = Job.maximum(:id)
+                               if last_job_id.nil?
+                                       last_job_id = 0
+                               end
+                       else
+                               last_job_id = last_id.to_i - 1
+                       end
+                       condition = "jobs.id <= #{last_job_id}"
+               else
+                       condition = "jobs.id > #{last_id}"
+               end
+
+               project = project + "%"
+
+               jobs = Job.find_by_sql("SELECT jobs.id
+                                                                        , CASE WHEN jobs.jtype like \"MULTI%\" THEN \"MULTI\"
+                                                                                        ELSE \"SINGLE\" END \"job_attribute\"
+                                                                FROM jobs 
+                                                                LEFT JOIN projects 
+                                                                  ON jobs.project_id = projects.id
+                                                                LEFT JOIN users
+                                                                  ON jobs.user_id = users.id
+                                                                LEFT JOIN supported_os
+                                                                  ON jobs.supported_os_id = supported_os.id
+                                                                LEFT JOIN distributions
+                                                                  ON jobs.distribution_id = distributions.id
+                                                                LEFT JOIN remote_build_servers
+                                                                  ON jobs.remote_build_server_id = remote_build_servers.id
+                                                                LEFT JOIN sources
+                                                                  ON jobs.source_id = sources.id
+                                                         WHERE #{condition}
+                                                               AND jobs.status IN (#{status})
+                                                               AND projects.name like '#{project}'
+                                                         ORDER BY jobs.id DESC
+                                                         LIMIT #{QUERY_CNT}")
+
+               #generate to XML
+               doc.Data {
+                       doc.JobList {
+                               jobs.each {|job_list|
+                                       job = get_job_info(job_list.id)
+
+                                       doc.Job {
+                                               doc.Id(job.job_id)
+                                               doc.Distribution(job.distribution_name)
+                                               doc.ProjectName(job.project_name)
+                                               doc.JobType(job.job_type)
+                                               doc.JobAttribute(job_list.job_attribute)
+                                               doc.ParentJobId(job.parent_job_id)
+                                               doc.Os(job.supported_os_name)
+                                               doc.Status(job.status)
+                                               doc.UserName(job.user_name)
+                                               doc.StartTime(job.start_time)
+                                               doc.EndTime(job.end_time)
+                                       }
+                               }
+                       }
+               }
+       end
+
+       def get_job_info(job_id)
+               jobs = Job.find_by_sql("SELECT jobs.id AS job_id
+                                                                        , jobs.jtype AS job_type
+                                                                        , jobs.status AS status
+                                                                        , jobs.parent_job_id AS parent_job_id
+                                                                        , DATE_FORMAT(jobs.start_time, '%Y-%m-%d %H:%i:%s') AS start_time
+                                                                        , DATE_FORMAT(jobs.end_time, '%Y-%m-%d %H:%i:%s') AS end_time
+                                                                        , CASE WHEN jobs.jtype like \"MULTI%\" THEN \"MULTI\"
+                                                                                        ELSE \"SINGLE\" END \"job_attribute\"
+                                                                    , projects.name AS project_name
+                                                                    , projects.ptype AS project_type
+                                                                    , projects.password AS project_password
+                                                                    , users.name AS user_name
+                                                                    , users.email AS user_email
+                                                                    , supported_os.name AS supported_os_name
+                                                                    , distributions.name AS distribution_name
+                                                                    , distributions.pkgsvr_url AS pkgsvr_url
+                                                                    , distributions.pkgsvr_addr AS pkgsvr_addr
+                                                                    , distributions.description AS distribution_desc
+                                                                    , remote_build_servers.svr_addr AS remote_build_server_addr
+                                                                        , remote_build_servers.description AS remote_build_server_desc
+                                                                        , sources.pkg_ver AS pkg_ver
+                                                                        , sources.location AS location
+                                                                 FROM jobs 
+                                                                 LEFT JOIN projects 
+                                                                   ON jobs.project_id = projects.id
+                                                                 LEFT JOIN users
+                                                                   ON jobs.user_id = users.id
+                                                                 LEFT JOIN supported_os
+                                                                   ON jobs.supported_os_id = supported_os.id
+                                                                 LEFT JOIN distributions
+                                                                   ON jobs.distribution_id = distributions.id
+                                                                 LEFT JOIN remote_build_servers
+                                                                   ON jobs.remote_build_server_id = remote_build_servers.id
+                                                                 LEFT JOIN sources
+                                                                   ON jobs.source_id = sources.id
+                                                                 WHERE jobs.id = #{job_id}")
+               return jobs[0]
+       end
+
+       def get_child_job_info(parent_job_id)
+               job = Job.find_by_sql("SELECT jobs.id AS job_id
+                                                                        , jobs.jtype AS job_type
+                                                                        , jobs.status AS status
+                                                                        , jobs.parent_job_id AS parent_job_id
+                                                                        , DATE_FORMAT(jobs.start_time, '%Y-%m-%d %H:%i:%s') AS start_time
+                                                                        , DATE_FORMAT(jobs.end_time, '%Y-%m-%d %H:%i:%s') AS end_time
+                                                                    , projects.name AS project_name
+                                                                    , projects.ptype AS project_type
+                                                                    , users.name AS user_name
+                                                                    , users.email AS user_email
+                                                                    , supported_os.name AS supported_os_name
+                                                                    , distributions.name AS distribution_name
+                                                                    , distributions.pkgsvr_url AS pkgsvr_url
+                                                                    , distributions.pkgsvr_addr AS pkgsvr_addr
+                                                                    , distributions.description AS distribution_desc
+                                                                    , remote_build_servers.svr_addr AS remote_build_server_addr
+                                                                        , remote_build_servers.description AS remote_build_server_desc
+                                                                        , sources.pkg_ver AS pkg_ver
+                                                                        , sources.location AS location
+                                                                 FROM jobs 
+                                                                 LEFT JOIN projects 
+                                                                   ON jobs.project_id = projects.id
+                                                                 LEFT JOIN users
+                                                                   ON jobs.user_id = users.id
+                                                                 LEFT JOIN supported_os
+                                                                   ON jobs.supported_os_id = supported_os.id
+                                                                 LEFT JOIN distributions
+                                                                   ON jobs.distribution_id = distributions.id
+                                                                 LEFT JOIN remote_build_servers
+                                                                   ON jobs.remote_build_server_id = remote_build_servers.id
+                                                                 LEFT JOIN sources
+                                                                   ON jobs.source_id = sources.id
+                                                                 WHERE jobs.parent_job_id = #{parent_job_id}")
+               return job
+       end
+
+       def log_more
+               @cursor = nil
+               @file = nil
+       
+               line_cnt = 999
+               conti= 1
+               id = params[:id]
+               puts id
+               line = params[:line].to_i
+       
+               # Get job information
+               job = get_job_info(id)
+               if job.nil?
+                       render :text => "Not found Job ID #{id}", :status => 406
+               end
+
+               if job.job_type == "MULTIBUILD"
+                       project_name = job.job_type
+               else
+                       project_name = job.project_name
+               end
+
+               # Get log file infomation
+               file_name = "log"
+               buildsvr_path = Server_config.find(:first, :conditions => ["property = ?", "path"])
+               directory = "#{buildsvr_path.value}/jobs/#{id}"
+       
+               # create the file path                                                                         
+               path = File.join(directory, file_name)                                                              
+       
+               # read the file                                                                               
+               if File.exist?(path)
+                       @cursor = File.size(path)
+                       @file = File.open(path, 'r')
+                       data = @file.readlines
+               end
+       
+               time = Time.new
+               timestamp = time.getlocal
+       
+               start_line = line 
+               last_line = start_line + line_cnt
+       
+               #count line
+               tok = nil
+               IO.popen("wc -l #{path}") do |wc|
+                       tok = wc.read.split(" ")
+               end
+               end_line = tok[0].to_i
+       
+               #check line
+               if last_line > end_line
+                       last_line = end_line
+               end
+       
+               #read log file
+               temp = nil
+               if start_line < end_line
+                       IO.popen("sed -n \"#{start_line},#{last_line}p\" #{path}") do |sed| 
+                               temp = sed.read
+                       end
+               else
+                       conti= 0
+               end
+       
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Responser {
+                       generate_xml_header(doc)
+                       doc.Data {
+                               doc.JobId(id)
+                               doc.Distribution(job.distribution_name)
+                               doc.Project(project_name)
+                               doc.Builder(job.user_name)
+                               doc.Status(job.status)
+                               doc.Time(timestamp)
+                               doc.Continue(conti)
+                               if temp
+                                       temp.each do |data|
+                                               doc.LogData(data, "Line" => line) 
+                                               line = line + 1
+                                       end
+                               end
+                       }
+               }
+       
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def cancelJob
+               id = params[:id]
+
+               # get job information
+               job = get_job_info(id)
+               if job.nil?
+                       render :text => "Not found Job ID #{id}", :status => 406
+                       return
+               end
+
+               # Check job builder
+               if get_user_email != job.user_email 
+                       if not is_admin(get_user_email)
+                               render :text => "You don't have authority to calcel.", :status => 406
+                               return
+                       end
+               end
+
+               # Excute command
+               begin
+                       Utils.sbi_cancel_command(id, job.project_password)
+               rescue => e
+                       render :text => e.message, :status => 406
+                       return
+               end
+               render :xml=> "<Message>OK</Message>"
+       end
+end
diff --git a/dibs-web/app/controllers/projects_controller.rb b/dibs-web/app/controllers/projects_controller.rb
new file mode 100644 (file)
index 0000000..2bb8c94
--- /dev/null
@@ -0,0 +1,407 @@
+=begin 
+ projects_controller.rb 
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 'json'
+
+class ProjectsController < ApplicationController
+
+  layout :myLayout
+  before_filter :check_login_status
+  respond_to :json
+
+  def myLayout
+       params[:action] == 'fileUpload' ? nil : 'application'
+  end
+       
+
+  def buildProject
+       # get information : dist_name, project_hash, password
+       change_group_list = params[:ChangeInfoList]
+
+       project_list = []
+       os_list = []
+       password_list = []
+
+       dist_name = nil
+       build_type = nil
+
+       change_group_list.each do |change_item|
+               dist_name = change_item[:distribution]
+               build_type = change_item[:buildType]
+               project_name = change_item[:projectName]
+               os = change_item[:os]
+
+               distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+               project = Project.find(:first, :conditions => ["name = ? AND distribution_id =?", project_name, distribution.id])
+
+               project_list.push project.name 
+               password_list.push project.password
+               os_list.push os
+       end
+
+       project_list.uniq!
+       os_list.uniq!
+       password_list.uniq!
+
+       if (project_list.length > 1) or (not (project_list[0].nil? or project_list[0].empty?))
+               # execute build command
+               begin
+                       Utils.sbi_build_command(build_type, dist_name, project_list, os_list, password_list, get_user_email)
+               rescue => e
+                       render :text => e.message, :status => 406
+                       return
+               end
+    
+               render :json => { :success => "OK!" }
+       else
+               render :text => "Can't build project", :status => 406
+       end
+
+  end
+
+  def queryPackageInfo(project_id, os_id)
+
+               source = Project.find_by_sql("SELECT sources.pkg_ver AS pkg_ver
+                                                                                        , DATE_FORMAT(jobs.start_time, '%Y-%m-%d %H:%i:%s') AS start_time
+                                                                                        , DATE_FORMAT(jobs.end_time, '%Y-%m-%d %H:%i:%s') AS end_time
+                                                                                        , jobs.source_id AS source_id
+                                                                                        , jobs.supported_os_id AS supported_os_id
+                                                                                        , users.name AS user_name
+                                                                                        , users.email AS user_email
+                                                                                 FROM projects
+                                                                                        , sources 
+                                                                                        , jobs
+                                                                                        , users
+                                                                                WHERE projects.id = sources.project_id
+                                                                                       AND jobs.source_id = sources.id 
+                                                                                       AND jobs.user_id = users.id
+                                                                                       AND projects.id = #{project_id}
+                                                                                       AND jobs.supported_os_id = #{os_id}
+                                                                               ORDER BY jobs.id DESC")
+
+
+               if source.nil?
+                       return nil
+               else
+                       return source[0]
+               end
+  end
+
+  def checkUserAccessProject(user_id, project_id)
+       row = Project.find_by_sql("SELECT COUNT(*) AS cnt
+                                                                 FROM user_groups
+                                                                    , groups
+                                                                    , group_project_accesses
+                                                                WHERE user_groups.group_id = groups.id
+                                                                  AND groups.id = group_project_accesses.group_id
+                                                                  AND user_groups.user_id = #{user_id}
+                                                                  AND group_project_accesses.project_id = #{project_id}")
+               if row[0].cnt > 0
+                       return TRUE
+               end
+
+       return FALSE
+  end
+
+  def queryProjectsInfoInDistribution
+       dist_name = params[:distribution]
+
+       user_id = get_user_id
+       distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+       projects = Project.find(:all, :conditions => ["distribution_id = ?", distribution.id], :order => "name")
+
+       #generate to XML
+       doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+       doc.Response {
+               generate_xml_header(doc)
+               doc.Data {
+                       doc.ProjectList {
+                               projects.each { |project|
+                                       doc.Project {
+                                               doc.Name(project.name)
+                                               doc.Type(project.ptype)
+                                               maintainer = User.find(:first, :conditions => ["id = ?", project.user_id])
+                                               if not maintainer.nil? 
+                                                       doc.Maintainer(maintainer.email)
+                                               else
+                                                       doc.Maintainer("")
+                                               end
+
+                                               if checkUserAccessProject(user_id, project.id)
+                                                       doc.GroupAccess("TRUE")
+                                               else
+                                                       doc.GroupAccess("FALSE")
+                                               end
+
+                                               os_list = ProjectOs.find(:all, :conditions => ["project_id = ?", project.id], :order => "supported_os_id")
+                                               os_list.each { |os|
+                                                       doc.ProjectOs {
+                                                               os_info = SupportedOs.find(:first, :conditions => ["id = ?", os.supported_os_id])
+                                                               doc.OsName(os_info.name)
+
+                                                               source = queryPackageInfo(project.id, os.supported_os_id) 
+                                                               if source.nil?
+                                                                       doc.Package {
+                                                                               doc.PackageName()
+                                                                               doc.PackageVersion()
+                                                                               doc.StartTime()
+                                                                               doc.EndTime()
+                                                                               doc.UserName()
+                                                                               doc.UserEmail()
+                                                                       }
+                                                               else
+                                                                       packageList = Package.find(:all, :conditions => ["source_id = ? AND supported_os_id = ?", source.source_id, source.supported_os_id])
+
+                                       
+                                                                       packageList.each { |package| 
+                                                                               doc.Package {
+                                                                                       doc.PackageName(package.pkg_name)
+                                                                                       doc.PackageVersion(source.pkg_ver)
+                                                                                       doc.StartTime(source.start_time)
+                                                                                       doc.EndTime(source.end_time)
+                                                                                       doc.UserName(source.user_name)
+                                                                                       doc.UserEmail(source.user_email)
+                                                                               }
+                                                                       }
+                                                               end
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       #send_data
+       render :text => out_string, :content_type => "text/xml"
+  end
+
+  def queryRunningProjectsInfoInDistribution
+       dist_name = params[:distribution]
+
+       running_project_list = Project.find_by_sql("SELECT projects.name
+                , projects.ptype
+                , jobs.status
+                , supported_os.name AS os_name
+                       FROM jobs 
+                                , projects
+                                , supported_os
+                                , distributions
+                       WHERE jobs.project_id = projects.id
+                               AND distributions.name = \"#{dist_name}\"
+                               AND projects.distribution_id = distributions.id
+                               AND NOT jobs.status in ('FINISHED', 'ERROR', 'CANCELED')
+                               AND supported_os.id = jobs.supported_os_id
+                       ORDER BY jobs.id")
+
+       #generate to XML
+       doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+       doc.Response {
+               generate_xml_header(doc)
+               doc.Data {
+                       if not running_project_list.nil?
+                               running_project_list.each do |run_project|
+                                       doc.RunProjectInfo {
+                                               doc.ProjectName(run_project.name)
+                                               doc.ProjectOs(run_project.os_name)
+                                               doc.ProjectType(run_project.ptype)
+                                               doc.Status(run_project.status)
+                                       }
+                               end
+                       end
+               }
+       }
+
+       #send_data
+       render :text => out_string, :content_type => "text/xml"
+  end
+
+  def queryJobStatus(project_id, supportes_os_id)
+       job = Job.find(:first, :conditions => ["status NOT IN ('FINISHED', 'ERROR') AND project_id = ? AND supported_os_id = ?", project_id, supported_os_id, ], :order => "id DESC")
+       if job.nil?
+               status = job.status
+       else
+               status = nil
+       end
+       return status
+  end
+
+  def queryProjectsInDistribution
+       dist_name = params[:distribution]
+
+       distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+       projects = Project.find(:all, :conditions => ["distribution_id = ?", distribution.id], :order => "name")
+       osList = SupportedOs.find(:all)
+
+       # check can build
+       project_access_list = []
+
+       # get all my project
+       group_list = get_group_list(get_user_email)
+
+       group_id_list = []
+       group_list.each { |group|
+               group_id_list.push group.id
+       }
+
+       group_name_list_string = 
+       group_access_project_list = GroupProjectAccess.find(:all, :conditions => ["group_id in (?)", group_id_list.join(",") ])
+       if not group_access_project_list.nil?
+               group_access_project_list.each do |access_project| 
+                       project_access_list.push access_project.project_id
+               end
+       end
+
+       #generate to XML
+       doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+       doc.Response {
+               generate_xml_header(doc)
+               doc.Data {
+                       doc.BuildServerInfo {
+                               if not osList.nil?
+                                       osList.each do |os|
+                                               doc.supportedOs(os.name)
+                                       end
+                               end
+                       }
+    
+                       projects.each do |project|
+                               if project.ptype.eql? "BINARY" 
+                                       bin = ProjectBin.find(:first, :conditions => ["project_id = ?", project.id])
+                                       if project_access_list.include? project.id 
+                                               doc.BinaryProject {
+                                                       doc.ProjectName(project.name)
+                                                       if not bin.nil? then
+                                                               doc.PackageName(bin.pkg_name)
+                                                       end
+                                               }
+                                       else
+                                               doc.OtherBinaryProject {
+                                                       doc.ProjectName(project.name)
+                                                       if not bin.nil? then
+                                                               doc.PackageName(bin.pkg_name)
+                                                       end
+                                               }
+                                       end
+                               else
+                                       buildOsNameList = []
+                                       prjOsLists = ProjectOs.find(:all, :conditions => ["project_id = ?", project.id])
+    
+                                       prjOsLists.each do |list| 
+                                               supported_os = SupportedOs.find(:first, :conditions => ["id = ?", list.supported_os_id])
+                                               buildOsNameList.push(supported_os.name)
+                                       end
+    
+                                       if project_access_list.include? project.id 
+                                               doc.Project {
+                                                       doc.ProjectName(project.name)
+                                                       doc.OsList(buildOsNameList.join(","))
+                                               }
+                                       else
+                                               doc.OtherProject {
+                                                       doc.ProjectName(project.name)
+                                                       doc.OsList(buildOsNameList.join(","))
+                                               }
+                                       end
+                               end
+    
+                       end 
+               }
+       }
+
+       #send_data
+       render :text => out_string, :content_type => "text/xml"
+
+  end
+
+  def queryDistribution
+       distribution_list = []
+
+       # get full distribution list
+       distributions = Distribution.all
+       distributions.each {|distribution| 
+               distribution_list.push distribution.name
+       }
+
+       #generate to XML
+       doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+       doc.Response {
+               generate_xml_header(doc)
+
+               doc.Data {
+                       if not distribution_list.nil?
+                               distribution_list.each do |distribution|
+                                       doc.DistributionName(distribution)
+                               end
+                       end
+               }
+       }
+       
+       #send_data
+       render :text => out_string, :content_type => "text/xml"
+  end
+
+  def projects
+  end
+
+  def fileUpload
+
+  end
+
+  def binaryFileUpload
+    dist_name = params[:distribution]
+    project = params[:project]
+    uploaded_io = params[:file]
+       file_path = Rails.root.join('public', 'data', uploaded_io.original_filename)
+    File.open(file_path, 'wb') do |file|
+       file.write(uploaded_io.read)
+    end
+
+       distribution = Distribution.find(:first, :conditions => ["name = ?", dist_name])
+       project = Project.find(:first, :conditions => ["name = ? AND distribution_id =?", project, distribution.id])
+       if project.nil? 
+               render :nothing => true
+               return
+       end
+
+       begin
+               Utils.sbi_register_command(distribution.name, file_path,  project.password, get_user_email)
+       rescue => e
+               render :text => e.message, :status => 406
+               return
+       end
+
+       render :nothing => true
+       return
+
+       render :text => uploaded_io.original_filename + " is uploaded.",
+                       :content_type => "text/xml"
+  end
+
+end
diff --git a/dibs-web/app/controllers/sessions_controller.rb b/dibs-web/app/controllers/sessions_controller.rb
new file mode 100644 (file)
index 0000000..9d90123
--- /dev/null
@@ -0,0 +1,107 @@
+=begin 
+ sessions_controller.rb 
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 SessionsController < ApplicationController
+       def new
+       end
+
+       def login
+               input_list = params[:ChangeInfoList]
+               input_item = input_list[0]
+
+               create_session(input_item[:Email], input_item[:Password])
+       end
+
+       def create_session(email, password)
+               user = User.authenticate(email, password)
+
+               if user
+                       group_list = get_group_list(user.email)
+                       if is_admin(user.email)
+                               admin = "TRUE"
+                       else
+                               admin = "FALSE"
+                       end
+
+                       session[:user_email] = user.email
+                       user_info = { :Message => 'Welcome!', 
+                                                       :Eamil => user.email, 
+                                                       :Name => user.name, 
+                                                       :Admin => admin,
+                                                 }
+                       group_info = nil
+                       group_list.map { |group|
+                               group_info = {:Group => [:GroupName => group.name, 
+                                                               :GroupAdmin => group.admin, 
+                                                               :GroupDescription => group.description] }
+                       }
+
+                       render :json => { :Result => 'SUCCESS', :UserInfo => user_info, :GroupInfo => group_info}
+                       puts user_info
+               else
+                       render :json => { :Result => 'ERROR', :UserInfo => {:Message => 'Fail login'} }
+               end
+               return
+       end
+
+       def logout
+               session[:user_email] = nil
+
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+
+               doc.LogOutInfo {
+                       doc.Message("Welcome...")
+                       doc.LogInTime("")
+                       doc.LogOutTime("")
+               }
+
+               render :text => out_string,
+                               :content_type => "text/xml"
+       end
+
+       def create
+               user = User.authenticate(params[:email], params[:password])
+
+               #generate to XML
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+
+               if user
+                       session[:user_email] = user.email
+                       redirect_to "/projects"
+               else
+                       flash.now.alert = "Invalid email or password"
+                       render "new"
+               end
+       end
+       
+       def destroy
+               session[:user_email] = nil
+               redirect_to root_url, :notice => "Logged out!"
+       end
+end
diff --git a/dibs-web/app/controllers/users_controller.rb b/dibs-web/app/controllers/users_controller.rb
new file mode 100644 (file)
index 0000000..0b830a1
--- /dev/null
@@ -0,0 +1,172 @@
+=begin 
+ users_controller.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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 UsersController < ApplicationController
+
+       def new
+               @user = User.new(params[:user])
+       end
+
+       def create
+               @user = User.new(params[:user])
+
+               if @user.save
+                       redirect_to "/projects", :notice => "Signed up!"
+               else
+                       render :action => "new"
+               end
+       end
+
+       def signup 
+               change_list = params[:ChangeInfoList]
+               change_item = change_list[0]
+
+               @user = User.new()
+               @user.email = change_item[:Email]
+               @user.name = change_item[:Name]
+               @user.password = change_item[:Password]
+               @user.password_confirmation = change_item[:PasswordConfirm]
+
+               if @user.save
+                       create_session(@user.email, @user.password)
+               else
+                       render :json => { :error => "Error"}, :status => 406
+               end
+
+       end
+
+       def create_session(email, password)
+               user = User.authenticate(email, password)
+
+               if user
+                       group_list = get_group_list(user.email)
+                       if is_admin(user.email)
+                               admin = "TRUE"
+                       else
+                               admin = "FALSE"
+                       end
+
+                       session[:user_email] = user.email
+                       user_info = { :Message => 'Welcome!', 
+                                                       :Eamil => user.email, 
+                                                       :Name => user.name, 
+                                                       :Admin => admin,
+                                                 }
+                       group_info = nil
+                       group_list.map { |group|
+                               group_info = {:Group => [:GroupName => group.name, 
+                                                               :GroupAdmin => group.admin, 
+                                                               :GroupDescription => group.description] }
+                       }
+
+                       render :json => { :Result => 'SUCCESS', :UserInfo => user_info, :GroupInfo => group_info}
+                       puts user_info
+               else
+                       render :json => { :Result => 'ERROR', :UserInfo => {:Message => 'Fail login'} }
+               end
+               return
+       end
+       
+       def show 
+               email = get_user_email
+               user = User.find(:first, :conditions => ["email = ?", email])
+
+               doc = Builder::XmlMarkup.new( :target => out_string = "", :indent => 2 )
+               doc.Response {
+                       generate_xml_header(doc)
+               
+                       doc.Data {
+                               doc.User {
+                                       doc.Name(user.name)
+                                       doc.Email(user.email)
+                                       doc.GroupList {
+                                               group_list = get_group_list(user.email)
+                                               group_list.each { |group|
+                                                               doc.GroupName(group.name)
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               #send_data
+               render :text => out_string, :content_type => "text/xml"
+       end
+
+       def modify
+               change_list = params[:ChangeInfoList]
+               change_item = change_list[0]
+               errmsg = ""
+
+               email = change_item[:Email]
+               name = change_item[:Name]
+               password = change_item[:Password]
+               password_confirm = change_item[:PasswordConfirm]
+
+               if email != get_user_email
+                       errmsg = "Can't modify email"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               if email.nil? or email.empty? 
+                       errmsg = "Email is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               if name.nil? or name.empty? 
+                       errmsg = "Name is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               if password.nil? or password.empty? 
+                       errmsg = "Password is empty"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+
+               if password != password_confirm
+                       errmsg = "Password is different"
+                       render :json => { :error => errmsg }, :status => 406
+                       return
+               end
+               user = User.find(:first, :conditions => ["email = ?", email])
+               user.name = name
+               user.password = password
+               user.password_confirmation = password_confirm
+               user.save
+
+               if errmsg.empty?
+                       render :json => { :success => "OK!" }
+               else
+                       render :json => { :error => errmsg }, :status => 406
+               end
+       end
+end
diff --git a/dibs-web/app/controllers/utils.rb b/dibs-web/app/controllers/utils.rb
new file mode 100644 (file)
index 0000000..b0e5f4b
--- /dev/null
@@ -0,0 +1,130 @@
+=begin 
+ utils.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+
+# constant
+BUILD_SERVER_ADDRESS = "127.0.0.1"
+
+class Utils < ApplicationController
+  def Utils.sbi_build_command(sub_cmd, distribution, project_list, os_list, password_list, email)
+       dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__))))
+       dibs_config = Server_config.find(:first, :conditions => ["property = \"port\""])
+       if dibs_config.nil?
+               raise RuntimeError, "Build sever not started"
+       else
+               dibs_address = BUILD_SERVER_ADDRESS + ":" + dibs_config.value
+       end
+
+       options = "-d #{dibs_address} --async "
+       options = options + " -N #{project_list.join(",")} -D #{distribution} " 
+       if (os_list.length > 1) or (not os_list[0].nil?)
+               options = options + " -o #{os_list.join(",")} "
+       end
+       if (password_list.length > 1) or (not (password_list[0].nil? or password_list[0].empty?))
+               options = options + " -w #{password_list.join(",")} "
+       end
+       if not email.nil?
+               options = options + " -U #{email} "
+       end
+
+       cmd = "#{dibs_path}/build-cli #{sub_cmd} #{options}"
+puts "Build command"
+puts "[[[#{cmd}]]]"
+
+       return execute_shell_return(cmd)
+  end
+
+  def Utils.sbi_register_command(distribution, file_path, password, email)
+       dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__))))
+       dibs_config = Server_config.find(:first, :conditions => ["property = \"port\""])
+       if dibs_config.nil?
+               raise RuntimeError, "Build sever not started"
+       else
+               dibs_address = BUILD_SERVER_ADDRESS + ":" + dibs_config.value
+       end
+
+       options = "-P #{file_path} -d #{dibs_address} -D #{distribution} --async "
+       if (not password.nil?)
+               options = options + " -w #{password}"
+       end
+       if not email.nil?
+               options = options + " -U #{email} "
+       end
+
+       cmd = "#{dibs_path}/build-cli register #{options}"
+puts "Register command"
+puts "[[[#{cmd}]]]"
+       return execute_shell_return(cmd)
+  end
+
+  def Utils.sbi_cancel_command(job_id, password)
+       dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__))))
+       dibs_config = Server_config.find(:first, :conditions => ["property = \"port\""])
+       if dibs_config.nil?
+               raise RuntimeError, "Build sever not started"
+       else
+               dibs_address = BUILD_SERVER_ADDRESS + ":" + dibs_config.value
+       end
+
+       if job_id.nil?
+               raise RuntimeError, "Invalid job id : #{job_id}"
+       end
+
+       options = "-d #{dibs_address} "
+       options = options + " -j #{job_id}"
+       if (not password.nil?)
+               options = options + " -w #{password}"
+       end
+
+       cmd = "#{dibs_path}/build-cli cancel #{options}"
+puts "Cancel command"
+puts "[[[#{cmd}]]]"
+       return execute_shell_return(cmd)
+  end
+
+  def Utils.sbi_fullbuild_command(server_name, dist_name)
+       dibs_path = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__))))
+
+       options = "-n #{server_name} --dist #{dist_name} "
+       cmd = "#{dibs_path}/build-svr fullbuild #{options}"
+puts "Fullbuild command"
+puts "[[[#{cmd}]]]"
+       return execute_shell_return(cmd)
+  end
+
+  def Utils.execute_shell_return(cmd)
+    result_lines = []
+    ret = false
+  
+    # get result
+    IO.popen("#{cmd}")
+    #system "#{cmd}"
+
+       return true
+  end
+
+end
diff --git a/dibs-web/app/helpers/admin_distribution_helper.rb b/dibs-web/app/helpers/admin_distribution_helper.rb
new file mode 100644 (file)
index 0000000..97c39f6
--- /dev/null
@@ -0,0 +1,2 @@
+module AdminDistributionHelper
+end
diff --git a/dibs-web/app/helpers/admin_group_helper.rb b/dibs-web/app/helpers/admin_group_helper.rb
new file mode 100644 (file)
index 0000000..9561d3b
--- /dev/null
@@ -0,0 +1,2 @@
+module AdminGroupHelper
+end
diff --git a/dibs-web/app/helpers/admin_helper.rb b/dibs-web/app/helpers/admin_helper.rb
new file mode 100644 (file)
index 0000000..d5c6d35
--- /dev/null
@@ -0,0 +1,2 @@
+module AdminHelper
+end
diff --git a/dibs-web/app/helpers/admin_project_helper.rb b/dibs-web/app/helpers/admin_project_helper.rb
new file mode 100644 (file)
index 0000000..7925981
--- /dev/null
@@ -0,0 +1,2 @@
+module AdminProjectHelper
+end
diff --git a/dibs-web/app/helpers/admin_server_helper.rb b/dibs-web/app/helpers/admin_server_helper.rb
new file mode 100644 (file)
index 0000000..5c7d70a
--- /dev/null
@@ -0,0 +1,2 @@
+module AdminServerHelper
+end
diff --git a/dibs-web/app/helpers/admin_user_helper.rb b/dibs-web/app/helpers/admin_user_helper.rb
new file mode 100644 (file)
index 0000000..3edd72d
--- /dev/null
@@ -0,0 +1,2 @@
+module AdminUserHelper
+end
diff --git a/dibs-web/app/helpers/application_helper.rb b/dibs-web/app/helpers/application_helper.rb
new file mode 100644 (file)
index 0000000..de6be79
--- /dev/null
@@ -0,0 +1,2 @@
+module ApplicationHelper
+end
diff --git a/dibs-web/app/helpers/jobs_helper.rb b/dibs-web/app/helpers/jobs_helper.rb
new file mode 100644 (file)
index 0000000..44c7bf6
--- /dev/null
@@ -0,0 +1,2 @@
+module JobsHelper
+end
diff --git a/dibs-web/app/helpers/projects_helper.rb b/dibs-web/app/helpers/projects_helper.rb
new file mode 100644 (file)
index 0000000..fc47f60
--- /dev/null
@@ -0,0 +1,4 @@
+module ProjectsHelper
+       def update_text(name)
+       end
+end
diff --git a/dibs-web/app/helpers/sessions_helper.rb b/dibs-web/app/helpers/sessions_helper.rb
new file mode 100644 (file)
index 0000000..309f8b2
--- /dev/null
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
diff --git a/dibs-web/app/helpers/users_helper.rb b/dibs-web/app/helpers/users_helper.rb
new file mode 100644 (file)
index 0000000..2310a24
--- /dev/null
@@ -0,0 +1,2 @@
+module UsersHelper
+end
diff --git a/dibs-web/app/mailers/.gitkeep b/dibs-web/app/mailers/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/dibs-web/app/models/.gitkeep b/dibs-web/app/models/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/dibs-web/app/models/distribution.rb b/dibs-web/app/models/distribution.rb
new file mode 100644 (file)
index 0000000..994dc84
--- /dev/null
@@ -0,0 +1,3 @@
+class Distribution < ActiveRecord::Base
+  attr_accessible :id, :name, :pkgsvr_url, :pkgsvr_addr, :status, :description
+end
diff --git a/dibs-web/app/models/group.rb b/dibs-web/app/models/group.rb
new file mode 100644 (file)
index 0000000..55595be
--- /dev/null
@@ -0,0 +1,5 @@
+class Group < ActiveRecord::Base
+#      has_many :user_groups
+#      has_many :users, :through => :user_groups
+       attr_accessible :name, :id
+end
diff --git a/dibs-web/app/models/group_project_access.rb b/dibs-web/app/models/group_project_access.rb
new file mode 100644 (file)
index 0000000..dee4f5e
--- /dev/null
@@ -0,0 +1,4 @@
+class GroupProjectAccess < ActiveRecord::Base
+       self.primary_key = 'group_id', 'project_id'
+       attr_accessible :group_id, :project_id, :build
+end
diff --git a/dibs-web/app/models/job.rb b/dibs-web/app/models/job.rb
new file mode 100644 (file)
index 0000000..3c15994
--- /dev/null
@@ -0,0 +1,3 @@
+class Job < ActiveRecord::Base
+  attr_accessible :distribution_id, :id, :supported_os_id, :project_id, :status, :user_id, :remote_build_server_id, :parent_job_id, :source_id, :jtype, :start_time, :end_time
+end
diff --git a/dibs-web/app/models/os_category.rb b/dibs-web/app/models/os_category.rb
new file mode 100644 (file)
index 0000000..a8fbee1
--- /dev/null
@@ -0,0 +1,4 @@
+class OsCategory < ActiveRecord::Base
+  set_table_name "os_category"
+  attr_accessible :id, :name
+end
diff --git a/dibs-web/app/models/package.rb b/dibs-web/app/models/package.rb
new file mode 100644 (file)
index 0000000..7e6b44f
--- /dev/null
@@ -0,0 +1,3 @@
+class Package < ActiveRecord::Base
+  attr_accessible :id, :pkg_name, :source_id, :supported_os_id
+end
diff --git a/dibs-web/app/models/project.rb b/dibs-web/app/models/project.rb
new file mode 100644 (file)
index 0000000..1c9d56e
--- /dev/null
@@ -0,0 +1,3 @@
+class Project < ActiveRecord::Base
+   attr_accessible :id, :distribution_id, :name, :ptype, :password
+end
diff --git a/dibs-web/app/models/project_bin.rb b/dibs-web/app/models/project_bin.rb
new file mode 100644 (file)
index 0000000..3252b0c
--- /dev/null
@@ -0,0 +1,3 @@
+class ProjectBin < ActiveRecord::Base
+  attr_accessible :project_id, :pkg_name
+end
diff --git a/dibs-web/app/models/project_git.rb b/dibs-web/app/models/project_git.rb
new file mode 100644 (file)
index 0000000..c0a5d4d
--- /dev/null
@@ -0,0 +1,3 @@
+class ProjectGit < ActiveRecord::Base
+  attr_accessible :project_id, :git_repos, :git_branch
+end
diff --git a/dibs-web/app/models/project_os.rb b/dibs-web/app/models/project_os.rb
new file mode 100644 (file)
index 0000000..670dab0
--- /dev/null
@@ -0,0 +1,4 @@
+class ProjectOs < ActiveRecord::Base
+       self.primary_key = 'project_id', 'supported_os_id'
+   attr_accessible :project_id, :supported_os_id
+end
diff --git a/dibs-web/app/models/remote_build_server.rb b/dibs-web/app/models/remote_build_server.rb
new file mode 100644 (file)
index 0000000..b02b1e5
--- /dev/null
@@ -0,0 +1,3 @@
+class RemoteBuildServer < ActiveRecord::Base
+  attr_accessible :id, :svr_addr, :description, :status, :max_job_count, :working_job_count, :waiting_job_count
+end
diff --git a/dibs-web/app/models/server_config.rb b/dibs-web/app/models/server_config.rb
new file mode 100644 (file)
index 0000000..68f2df8
--- /dev/null
@@ -0,0 +1,3 @@
+class Server_config < ActiveRecord::Base
+  attr_accessible :property, :value
+end
diff --git a/dibs-web/app/models/source.rb b/dibs-web/app/models/source.rb
new file mode 100644 (file)
index 0000000..f8bd214
--- /dev/null
@@ -0,0 +1,3 @@
+class Source < ActiveRecord::Base
+  attr_accessible :id, :location, :pkg_ver, :project_id
+end
diff --git a/dibs-web/app/models/supported_os.rb b/dibs-web/app/models/supported_os.rb
new file mode 100644 (file)
index 0000000..c37b19f
--- /dev/null
@@ -0,0 +1,3 @@
+class SupportedOs < ActiveRecord::Base
+  attr_accessible :id, :os_category_id, :name
+end
diff --git a/dibs-web/app/models/sync_pkg_server.rb b/dibs-web/app/models/sync_pkg_server.rb
new file mode 100644 (file)
index 0000000..0863806
--- /dev/null
@@ -0,0 +1,3 @@
+class SyncPkgServer < ActiveRecord::Base
+  attr_accessible :description, :distribution_id, :id, :period, :pkgsvr_url
+end
diff --git a/dibs-web/app/models/sync_project.rb b/dibs-web/app/models/sync_project.rb
new file mode 100644 (file)
index 0000000..b860a7a
--- /dev/null
@@ -0,0 +1,3 @@
+class SyncProject < ActiveRecord::Base
+  attr_accessible :project_id, :sync_pkg_server_id
+end
diff --git a/dibs-web/app/models/user.rb b/dibs-web/app/models/user.rb
new file mode 100644 (file)
index 0000000..ebfb5f1
--- /dev/null
@@ -0,0 +1,29 @@
+class User < ActiveRecord::Base
+#      has_many :user_groups
+#      has_many :groups, :through => :user_groups
+       attr_accessible :id, :email, :password, :password_confirmation, :name
+
+       attr_accessor :password
+       before_save :encrypt_password
+
+       validates_uniqueness_of :email
+       validates_presence_of :email
+       validates_confirmation_of :password
+       validates_presence_of :password, :on => :create
+
+       def self.authenticate(email, password)
+               user = find_by_email(email)
+               if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
+                       user
+               else
+                       nil
+               end
+       end
+
+       def encrypt_password
+               if password.present?
+                       self.password_salt = BCrypt::Engine.generate_salt
+                       self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
+               end
+       end
+end
diff --git a/dibs-web/app/models/user_group.rb b/dibs-web/app/models/user_group.rb
new file mode 100644 (file)
index 0000000..d963db5
--- /dev/null
@@ -0,0 +1,7 @@
+class UserGroup < ActiveRecord::Base
+#      belongs_to :users
+#      belongs_to :groups
+       self.primary_key = 'group_id'
+       self.primary_key = 'user_id'
+       attr_accessible :group_id, :status, :user_id
+end
diff --git a/dibs-web/config.ru b/dibs-web/config.ru
new file mode 100644 (file)
index 0000000..536e8d2
--- /dev/null
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment',  __FILE__)
+run Dibs::Application
diff --git a/dibs-web/config/application.rb b/dibs-web/config/application.rb
new file mode 100644 (file)
index 0000000..1e8680c
--- /dev/null
@@ -0,0 +1,62 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+if defined?(Bundler)
+  # If you precompile assets before deploying to production, use this line
+  Bundler.require(*Rails.groups(:assets => %w(development test)))
+  # If you want your assets lazily compiled in production, use this line
+  # Bundler.require(:default, :assets, Rails.env)
+end
+
+module Dibs
+  class Application < Rails::Application
+    # Settings in config/environments/* take precedence over those specified here.
+    # Application configuration should go into files in config/initializers
+    # -- all .rb files in that directory are automatically loaded.
+
+    # Custom directories with classes and modules you want to be autoloadable.
+    # config.autoload_paths += %W(#{config.root}/extras)
+
+    # Only load the plugins named here, in the order given (default is alphabetical).
+    # :all can be used as a placeholder for all plugins not explicitly named.
+    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+    # Activate observers that should always be running.
+    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+
+    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+    # config.time_zone = 'Central Time (US & Canada)'
+
+    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+    # config.i18n.default_locale = :de
+
+    # Configure the default encoding used in templates for Ruby 1.9.
+    config.encoding = "utf-8"
+
+    # Configure sensitive parameters which will be filtered from the log file.
+    config.filter_parameters += [:password]
+
+    # Enable escaping HTML in JSON.
+    config.active_support.escape_html_entities_in_json = true
+
+    # Use SQL instead of Active Record's schema dumper when creating the database.
+    # This is necessary if your schema can't be completely dumped by the schema dumper,
+    # like if you have constraints or database-specific column types
+    # config.active_record.schema_format = :sql
+
+    # Enforce whitelist mode for mass assignment.
+    # This will create an empty whitelist of attributes available for mass-assignment for all models
+    # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
+    # parameters by using an attr_accessible or attr_protected declaration.
+    config.active_record.whitelist_attributes = true
+
+    # Enable the asset pipeline
+    config.assets.enabled = true
+
+    # Version of your assets, change this if you want to expire all your assets
+    config.assets.version = '1.0'
+  end
+end
diff --git a/dibs-web/config/boot.rb b/dibs-web/config/boot.rb
new file mode 100644 (file)
index 0000000..4489e58
--- /dev/null
@@ -0,0 +1,6 @@
+require 'rubygems'
+
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
diff --git a/dibs-web/config/database.yml b/dibs-web/config/database.yml
new file mode 100644 (file)
index 0000000..319f61e
--- /dev/null
@@ -0,0 +1,46 @@
+# SQLite version 3.x
+#   gem install sqlite3
+#
+#   Ensure the SQLite 3 gem is defined in your Gemfile
+#   gem 'sqlite3'
+# development:
+#   adapter: sqlite3
+#   database: db/development.sqlite3
+#   pool: 5
+#   timeout: 5000
+# 
+# # Warning: The database defined as "test" will be erased and
+# # re-generated from your development database when you run "rake".
+# # Do not set this db to the same as development or production.
+ test:
+   adapter: 
+   encoding:
+   host:
+   port:
+   database:
+   username:
+   password:
+   pool:
+   timeout: 
+ production:
+   adapter: 
+   encoding:
+   host:
+   port:
+   database:
+   username:
+   password:
+   pool:
+   timeout: 
+
+ development:
+   adapter: 
+   encoding: 
+   host: 
+   port: 
+   database: 
+   username: 
+   password: 
+   pool: 
+   timeout: 
diff --git a/dibs-web/config/environment.rb b/dibs-web/config/environment.rb
new file mode 100644 (file)
index 0000000..b3360a8
--- /dev/null
@@ -0,0 +1,7 @@
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+Dibs::Application.initialize!
+
+Rails.logger = Logger.new(STDOUT)
diff --git a/dibs-web/config/environments/development.rb b/dibs-web/config/environments/development.rb
new file mode 100644 (file)
index 0000000..f2b6b9b
--- /dev/null
@@ -0,0 +1,37 @@
+Dibs::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # In the development environment your application's code is reloaded on
+  # every request. This slows down response time but is perfect for development
+  # since you don't have to restart the web server when you make code changes.
+  config.cache_classes = false
+
+  # Log error messages when you accidentally call methods on nil.
+  config.whiny_nils = true
+
+  # Show full error reports and disable caching
+  config.consider_all_requests_local       = true
+  config.action_controller.perform_caching = false
+
+  # Don't care if the mailer can't send
+  config.action_mailer.raise_delivery_errors = false
+
+  # Print deprecation notices to the Rails logger
+  config.active_support.deprecation = :log
+
+  # Only use best-standards-support built into browsers
+  config.action_dispatch.best_standards_support = :builtin
+
+  # Raise exception on mass assignment protection for Active Record models
+  config.active_record.mass_assignment_sanitizer = :strict
+
+  # Log the query plan for queries taking more than this (works
+  # with SQLite, MySQL, and PostgreSQL)
+  config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+  # Do not compress assets
+  config.assets.compress = false
+
+  # Expands the lines which load the assets
+  config.assets.debug = true
+end
diff --git a/dibs-web/config/environments/production.rb b/dibs-web/config/environments/production.rb
new file mode 100644 (file)
index 0000000..9fb3183
--- /dev/null
@@ -0,0 +1,67 @@
+Dibs::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # Code is not reloaded between requests
+  config.cache_classes = true
+
+  # Full error reports are disabled and caching is turned on
+  config.consider_all_requests_local       = false
+  config.action_controller.perform_caching = true
+
+  # Disable Rails's static asset server (Apache or nginx will already do this)
+  config.serve_static_assets = false
+
+  # Compress JavaScripts and CSS
+  config.assets.compress = true
+
+  # Don't fallback to assets pipeline if a precompiled asset is missed
+  config.assets.compile = false
+
+  # Generate digests for assets URLs
+  config.assets.digest = true
+
+  # Defaults to nil and saved in location specified by config.assets.prefix
+  # config.assets.manifest = YOUR_PATH
+
+  # Specifies the header that your server uses for sending files
+  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+  # config.force_ssl = true
+
+  # See everything in the log (default is :info)
+  # config.log_level = :debug
+
+  # Prepend all log lines with the following tags
+  # config.log_tags = [ :subdomain, :uuid ]
+
+  # Use a different logger for distributed setups
+  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+  # Use a different cache store in production
+  # config.cache_store = :mem_cache_store
+
+  # Enable serving of images, stylesheets, and JavaScripts from an asset server
+  # config.action_controller.asset_host = "http://assets.example.com"
+
+  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
+  # config.assets.precompile += %w( search.js )
+
+  # Disable delivery errors, bad email addresses will be ignored
+  # config.action_mailer.raise_delivery_errors = false
+
+  # Enable threaded mode
+  # config.threadsafe!
+
+  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+  # the I18n.default_locale when a translation can not be found)
+  config.i18n.fallbacks = true
+
+  # Send deprecation notices to registered listeners
+  config.active_support.deprecation = :notify
+
+  # Log the query plan for queries taking more than this (works
+  # with SQLite, MySQL, and PostgreSQL)
+  # config.active_record.auto_explain_threshold_in_seconds = 0.5
+end
diff --git a/dibs-web/config/environments/test.rb b/dibs-web/config/environments/test.rb
new file mode 100644 (file)
index 0000000..e6b8932
--- /dev/null
@@ -0,0 +1,37 @@
+Dibs::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # The test environment is used exclusively to run your application's
+  # test suite. You never need to work with it otherwise. Remember that
+  # your test database is "scratch space" for the test suite and is wiped
+  # and recreated between test runs. Don't rely on the data there!
+  config.cache_classes = true
+
+  # Configure static asset server for tests with Cache-Control for performance
+  config.serve_static_assets = true
+  config.static_cache_control = "public, max-age=3600"
+
+  # Log error messages when you accidentally call methods on nil
+  config.whiny_nils = true
+
+  # Show full error reports and disable caching
+  config.consider_all_requests_local       = true
+  config.action_controller.perform_caching = false
+
+  # Raise exceptions instead of rendering exception templates
+  config.action_dispatch.show_exceptions = false
+
+  # Disable request forgery protection in test environment
+  config.action_controller.allow_forgery_protection    = false
+
+  # Tell Action Mailer not to deliver emails to the real world.
+  # The :test delivery method accumulates sent emails in the
+  # ActionMailer::Base.deliveries array.
+  config.action_mailer.delivery_method = :test
+
+  # Raise exception on mass assignment protection for Active Record models
+  config.active_record.mass_assignment_sanitizer = :strict
+
+  # Print deprecation notices to the stderr
+  config.active_support.deprecation = :stderr
+end
diff --git a/dibs-web/config/initializers/backtrace_silencers.rb b/dibs-web/config/initializers/backtrace_silencers.rb
new file mode 100644 (file)
index 0000000..59385cd
--- /dev/null
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/dibs-web/config/initializers/inflections.rb b/dibs-web/config/initializers/inflections.rb
new file mode 100644 (file)
index 0000000..5d8d9be
--- /dev/null
@@ -0,0 +1,15 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+#   inflect.plural /^(ox)$/i, '\1en'
+#   inflect.singular /^(ox)en/i, '\1'
+#   inflect.irregular 'person', 'people'
+#   inflect.uncountable %w( fish sheep )
+# end
+#
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections do |inflect|
+#   inflect.acronym 'RESTful'
+# end
diff --git a/dibs-web/config/initializers/mime_types.rb b/dibs-web/config/initializers/mime_types.rb
new file mode 100644 (file)
index 0000000..72aca7e
--- /dev/null
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register_alias "text/html", :iphone
diff --git a/dibs-web/config/initializers/secret_token.rb b/dibs-web/config/initializers/secret_token.rb
new file mode 100644 (file)
index 0000000..d99b878
--- /dev/null
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+Dibs::Application.config.secret_token = '7971db0f7470719db67c53a48ec8906f77b093334897b37d3c7de71298f18d1b4c92d56a8e158884f656ad4620f495abdef4f1a00b10498d8fde21a396c7171a'
diff --git a/dibs-web/config/initializers/session_store.rb b/dibs-web/config/initializers/session_store.rb
new file mode 100644 (file)
index 0000000..21ce5e6
--- /dev/null
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+Dibs::Application.config.session_store :cookie_store, :key => '_dibs_session'
+
+# Use the database for sessions instead of the cookie-based default,
+# which shouldn't be used to store highly confidential information
+# (create the session table with "rails generate session_migration")
+# Dibs::Application.config.session_store :active_record_store
diff --git a/dibs-web/config/initializers/wrap_parameters.rb b/dibs-web/config/initializers/wrap_parameters.rb
new file mode 100644 (file)
index 0000000..da4fb07
--- /dev/null
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+  wrap_parameters :format => [:json]
+end
+
+# Disable root element in JSON by default.
+ActiveSupport.on_load(:active_record) do
+  self.include_root_in_json = false
+end
diff --git a/dibs-web/config/locales/en.yml b/dibs-web/config/locales/en.yml
new file mode 100644 (file)
index 0000000..179c14c
--- /dev/null
@@ -0,0 +1,5 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+en:
+  hello: "Hello world"
diff --git a/dibs-web/config/routes.rb b/dibs-web/config/routes.rb
new file mode 100644 (file)
index 0000000..5d0385e
--- /dev/null
@@ -0,0 +1,179 @@
+=begin 
+ routes.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+
+Dibs::Application.routes.draw do
+    root :to => "sessions#new"
+
+       get "sessions/new" => "sessions#new"
+
+       resources :users
+
+    get "jobs" => "jobs#list"
+    
+       get "projects" => "projects#projects"
+       get "projects/fileUpload"
+    
+       get "signup" => "users#new", :as => "signup"
+
+       post "login" => "sessions#create"
+       get "logout" => "sessions#destroy", :as => "logout"
+       
+       
+       # For asynchronous call
+
+       post "users/signup"
+       post "users/modify"
+
+       post "sessions/login"
+       delete "sessions/logout"
+
+    get "jobs/list/all/:distribution/:status/:lastID" => "jobs#listAll", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+    get "jobs/list/user/:user/:distribution/:status/:lastID" => "jobs#listSearchUser", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+    get "jobs/list/group/:group/:distribution/:status/:lastID" => "jobs#listSearchGroup", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+    get "jobs/list/project/:project/:distribution/:status/:lastID" => "jobs#listSearchProject" , :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/, :project => /[0-9A-Za-z\-\.]+/ }
+    get "jobs/list/date/:date/:distribution/:status/:lastID" => "jobs#listSearchDate", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+
+       match "jobs/update" => "jobs#updateList", :format => "json"
+       match "jobs/log/:id" => "jobs#log"
+       match "jobs/log/:id/:line" => "jobs#log_more"
+       match "jobs/cancel/:id" => "jobs#cancelJob"
+
+
+       get "projects/queryDistribution"
+       match "projects/queryProject/:distribution" => "projects#queryProject", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+       post "projects/binaryFileUpload"
+       
+       # projects
+       match "projects/queryRunningProjectsInfoInDistribution/:distribution" => "projects#queryRunningProjectsInfoInDistribution", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+       match "projects/queryProjectsInfoInDistribution/:distribution" => "projects#queryProjectsInfoInDistribution", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+       match "projects/queryProjectsInDistribution/:distribution" => "projects#queryProjectsInDistribution" , :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+       post "projects/buildProject" 
+
+       # admin group
+       get "admin_group/queryAllGroup" 
+       match "admin_group/queryGroupInfo/:groupName" => "admin_group#queryGroupInfo"
+       post "admin_group/addGroup"
+       post "admin_group/removeGroup"
+       post "admin_group/modifyGroup"
+
+       # admin user
+       get "admin_user/queryAllUser" 
+       post "admin_user/removeUser" 
+       post "admin_user/modifyUser" 
+
+       # admin server
+       get "admin_server/queryAllServer" 
+       post "admin_server/addRemoteBuildServer" 
+       post "admin_server/removeRemoteBuildServer" 
+       post "admin_server/modifyRemoteBuildServer" 
+       post "admin_server/addOsCategory" 
+       post "admin_server/removeOsCategory" 
+       post "admin_server/modifyOsCategory" 
+       post "admin_server/addSupportedOS" 
+       post "admin_server/removeSupportedOS" 
+       post "admin_server/modifySupportedOS" 
+       post "admin_server/addServerInfo" 
+       post "admin_server/removeServerInfo" 
+       post "admin_server/modifyServerInfo" 
+
+       # admin project 
+       get "admin_project/queryAllProject" 
+       match "admin_project/queryProjectsInDistributionForAdmin/:distribution" => "admin_project#queryProjectsInDistributionForAdmin", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ }
+       post "admin_project/addProject" 
+       post "admin_project/removeProject" 
+       post "admin_project/modifyProject" 
+
+       # admin distribution
+       get "admin_distribution/queryAllDistribution" 
+       match "admin_distribution/queryDistributionInfo/:distribution" => "admin_distribution#queryDistributionInfo", :constraints => { :distribution => /[0-9A-Za-z\-\.\_]+/ } 
+       post "admin_distribution/addDistribution" 
+       post "admin_distribution/removeDistribution" 
+       post "admin_distribution/modifyDistribution" 
+
+       post "admin_distribution/fullBuildDistribution" 
+
+       get "admin/queryAllOS" 
+       get "admin/queryAllOSCategory" 
+
+       # The priority is based upon order of creation:
+       # first created -> highest priority.
+       
+       # Sample of regular route:
+       #   match 'products/:id' => 'catalog#view'
+       # Keep in mind you can assign values other than :controller and :action
+       
+       # Sample of named route:
+       #   match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
+       # This route can be invoked with purchase_url(:id => product.id)
+       
+       # Sample resource route (maps HTTP verbs to controller actions automatically):
+       #   resources :products
+       
+       # Sample resource route with options:
+       #   resources :products do
+       #     member do
+       #       get 'short'
+       #       post 'toggle'
+       #     end
+       #
+       #     collection do
+       #       get 'sold'
+       #     end
+       #   end
+       
+       # Sample resource route with sub-resources:
+       #   resources :products do
+       #     resources :comments, :sales
+       #     resource :seller
+       #   end
+       
+       # Sample resource route with more complex sub-resources
+       #   resources :products do
+       #     resources :comments
+       #     resources :sales do
+       #       get 'recent', :on => :collection
+       #     end
+       #   end
+       
+       # Sample resource route within a namespace:
+       #   namespace :admin do
+       #     # Directs /admin/products/* to Admin::ProductsController
+       #     # (app/controllers/admin/products_controller.rb)
+       #     resources :products
+       #   end
+       
+       # You can have the root of your site routed with "root"
+       # just remember to delete public/index.html.
+       # root :to => 'welcome#index'
+       
+       # See how all your routes lay out with "rake routes"
+       
+       # This is a legacy wild controller route that's not recommended for RESTful applications.
+       # Note: This route will make all actions in every controller accessible via GET requests.
+       # match ':controller(/:action(/:id))(.:format)'
+end
diff --git a/dibs-web/db/schema.rb b/dibs-web/db/schema.rb
new file mode 100644 (file)
index 0000000..f0ab07e
--- /dev/null
@@ -0,0 +1,76 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended to check this file into your version control system.
+
+ActiveRecord::Schema.define(:version => 20121024015858) do
+
+  create_table "distributions", :force => true do |t|
+    t.string   "name"
+    t.string   "pkgsvr_url"
+    t.string   "pkgsvr_addr"
+    t.datetime "created_at",  :null => false
+    t.datetime "updated_at",  :null => false
+  end
+
+  create_table "group_rights", :force => true do |t|
+    t.integer  "group_id"
+    t.integer  "project_id"
+    t.string   "build"
+    t.datetime "created_at", :null => false
+    t.datetime "updated_at", :null => false
+  end
+
+  create_table "groups", :force => true do |t|
+    t.string   "group_name"
+    t.datetime "created_at", :null => false
+    t.datetime "updated_at", :null => false
+  end
+
+  create_table "jobs", :force => true do |t|
+    t.string   "job_id",        :null => false
+    t.string   "project_name"
+    t.string   "distribution"
+    t.string   "job_attribute"
+    t.string   "os"
+    t.string   "status"
+    t.integer  "user_id"
+    t.string   "parent_id"
+    t.datetime "created_at",    :null => false
+    t.datetime "updated_at",    :null => false
+  end
+
+  create_table "projects", :force => true do |t|
+    t.string   "project_name"
+    t.string   "distribution_name"
+    t.string   "project_type"
+    t.string   "os_list"
+    t.string   "password"
+    t.datetime "created_at",        :null => false
+    t.datetime "updated_at",        :null => false
+  end
+
+  create_table "supported_os", :force => true do |t|
+    t.string   "name"
+    t.datetime "created_at", :null => false
+    t.datetime "updated_at", :null => false
+  end
+
+  create_table "users", :force => true do |t|
+    t.string   "email"
+    t.string   "user_name"
+    t.string   "password_hash"
+    t.string   "password_salt"
+    t.integer  "group_id"
+    t.datetime "created_at",    :null => false
+    t.datetime "updated_at",    :null => false
+  end
+
+end
diff --git a/dibs-web/db/seeds.rb b/dibs-web/db/seeds.rb
new file mode 100644 (file)
index 0000000..d34dfa0
--- /dev/null
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+#   cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
+#   Mayor.create(:name => 'Emanuel', :city => cities.first)
diff --git a/dibs-web/doc/README_FOR_APP b/dibs-web/doc/README_FOR_APP
new file mode 100644 (file)
index 0000000..fe41f5c
--- /dev/null
@@ -0,0 +1,2 @@
+Use this README file to introduce your application and point to useful places in the API for learning more.
+Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
diff --git a/dibs-web/public/.project b/dibs-web/public/.project
new file mode 100644 (file)
index 0000000..acb2d68
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>dibs</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.wst.common.project.facet.core.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>json.validation.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.jslint.nature.JSLintBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.css.nature.CSSBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.wst.validation.validationbuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.project.builder.WebBuilder</name>
+                       <arguments>
+                               <dictionary>
+                                       <key>usedLibraryType</key>
+                                       <value>jQueryMobile</value>
+                               </dictionary>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>json.validation.nature</nature>
+               <nature>org.tizen.web.jslint.nature.JSLintNature</nature>
+               <nature>org.tizen.web.css.nature.CSSNature</nature>
+               <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+               <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+               <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+               <nature>org.tizen.web.project.builder.WebNature</nature>
+       </natures>
+</projectDescription>
diff --git a/dibs-web/public/404.html b/dibs-web/public/404.html
new file mode 100644 (file)
index 0000000..9a48320
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>The page you were looking for doesn't exist (404)</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/404.html -->
+  <div class="dialog">
+    <h1>The page you were looking for doesn't exist.</h1>
+    <p>You may have mistyped the address or the page may have moved.</p>
+  </div>
+</body>
+</html>
diff --git a/dibs-web/public/422.html b/dibs-web/public/422.html
new file mode 100644 (file)
index 0000000..83660ab
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>The change you wanted was rejected (422)</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/422.html -->
+  <div class="dialog">
+    <h1>The change you wanted was rejected.</h1>
+    <p>Maybe you tried to change something you didn't have access to.</p>
+  </div>
+</body>
+</html>
diff --git a/dibs-web/public/500.html b/dibs-web/public/500.html
new file mode 100644 (file)
index 0000000..f3648a0
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>We're sorry, but something went wrong (500)</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/500.html -->
+  <div class="dialog">
+    <h1>We're sorry, but something went wrong.</h1>
+  </div>
+</body>
+</html>
diff --git a/dibs-web/public/config.xml b/dibs-web/public/config.xml
new file mode 100644 (file)
index 0000000..4ff99b6
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://172.21.110.234:3300" version="1.0" viewmodes="fullscreen">
+    <tizen:application id="q3tpr9HXDs" required_version="1.0"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>test</name>
+</widget>
diff --git a/dibs-web/public/favicon.ico b/dibs-web/public/favicon.ico
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/dibs-web/public/index.html b/dibs-web/public/index.html
new file mode 100644 (file)
index 0000000..e132087
--- /dev/null
@@ -0,0 +1,1017 @@
+<!--
+ index.html
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+-->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="ko">
+<head>
+       <title>DIBS 2.0</title>
+       
+       <meta charset="utf-8">
+       <meta http-equiv="X-UA-Compatible" content="IE=9" />
+       <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+       <meta name="description" content="A master-detail template generated by Tizen Web IDE"/>
+
+       <link rel="stylesheet" href="stylesheets/jquery.mobile-1.1.0.css"/>
+       <link rel="stylesheet" href="stylesheets/jqm-docs.css"/>
+       <link rel="stylesheet" href="stylesheets/style.css"/>
+       
+       <script src="javascripts/jquery-1.7.1.js"></script>
+       <script src="javascripts/jqm-docs.js"></script>
+       <script src="javascripts/jquery.mobile-1.1.0.js"></script>
+       <script src="javascripts/popup-window.js"></script>
+
+       <script src="javascripts/main.js"></script>
+       <script src="javascripts/dibs-api.js"></script>
+       <script src="javascripts/session.js"></script>
+       <script src="javascripts/user.js"></script>
+       <script src="javascripts/build.js"></script>
+       <script src="javascripts/projects.js"></script>
+       <script src="javascripts/jobs.js"></script>
+       <script src="javascripts/admin-user.js"></script>
+       <script src="javascripts/admin-user-modify.js"></script>
+       <script src="javascripts/admin-group.js"></script>
+       <script src="javascripts/admin-group-add.js"></script>
+       <script src="javascripts/admin-group-modify.js"></script>
+       <script src="javascripts/admin-project.js"></script>
+       <script src="javascripts/admin-project-add.js"></script>
+       <script src="javascripts/admin-project-modify.js"></script>
+       <script src="javascripts/admin-distribution.js"></script>
+       <script src="javascripts/admin-distribution-add.js"></script>
+       <script src="javascripts/admin-distribution-modify.js"></script>
+       <script src="javascripts/admin-server.js"></script>
+       <script src="javascripts/admin-server-add.js"></script>
+       <script src="javascripts/admin-server-modify.js"></script>
+       <script src="javascripts/admin-server-remove.js"></script>
+</head>
+
+<body>
+       <div data-role="page" id="index" class="type-interior">
+               <div data-role="header" data-theme="a">
+                       <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+                       <h1>DIBS 2.0</h1>
+                       <div class="sessionInfo">
+                       </div>
+               </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <h2>Welcome to DIBS</h2>
+                               <ul>
+                                       <li>This system is support to build project.
+                               </ul>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="index-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->
+       
+       <div data-role="page" id="login">
+               <div data-role="header"  data-theme="e" >
+                       <h1>Log in</h1>
+               </div>
+               <div data-role="content">
+                       <form id="loginForm">
+                               <label for="login-email" style="text-align: left; font-size: 12px">Email</label>
+                               <input id="login-email" name="email" type="text" style="font-size: 12px"/>
+                               <label for="login-password" style="text-align: left; font-size: 12px">Password</label>
+                               <input id="login-password" name="password" type="password" style="font-size: 12px"/>
+                               <br/>
+                               <div data-role="controlgroup" data-type="horizontal">   
+                                       <a href="#" data-rel="back" data-role="button" data-mini="true" >Cancel</a>
+                                       <a href="#" onClick="sessionLogin()" data-role="button" data-mini="true" >Log in</a>
+                               </div>
+                       </form>
+               </div> 
+       </div><!-- /page -->
+
+       <div data-role="page" id="signup" >
+               <div data-role="header"  data-theme="e" >
+                       <h1>Sign up</h1>
+               </div>
+               <div data-role="content">
+                       <form id="signupForm">
+                               <label for="user-email" style="text-align: left; font-size: 12px">Email</label>
+                               <input id="user-email" name="user[email]" type="text" style="font-size: 12px"/>
+                               <label for="user-name" style="text-align: left; font-size: 12px">Name</label>
+                               <input id="user-name" name="user[name]" type="text" style="font-size: 12px"/>
+                               <label for="user-password" style="text-align: left; font-size: 12px">Password</label>
+                               <input id="user-password" name="user[password]" type="password" style="font-size: 12px"/>
+                               <label for="user-password-confirmation" style="text-align: left; font-size: 12px">Password Comfirmation</label>
+                               <input id="user-password-confirmation" name="user[password_confirmation]" type="password" style="font-size: 12px"/>
+                               <div data-role="controlgroup" id="applyGroupRadio">
+                               </div>
+                               <div data-role="controlgroup" data-type="horizontal">
+                                       <a href="#" data-rel="back" data-role="button" data-mini="true" >Cancel</a>
+                                       <a href="#" onClick="userSignUp()" data-role="button" data-mini="true" data-inline="true">Sign up</a>
+                               </div>
+                       </form> 
+                       <p id="signupErrorMessage" style="text-align: left; font-size: 12px font-color: red">
+                       </p>
+               </div> 
+       </div><!-- /page -->
+
+       <div data-role="page" id="notification" >
+               <div data-role="header"  data-theme="e" >
+                       <h1></h1>
+               </div>
+               <div data-role="content">
+               </div> 
+       </div><!-- /page -->
+       
+       <div data-role="page" id="projects" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <div data-role="fieldcontain" style="text-align: center; font-size: 14px;">
+                                       <select id="projects-select-distribution"  data-native-menu="false" onchange='projectsQueryProjectListType("MY")'>
+                                       </select>
+                               </div>
+                               <br>
+                               <div id="projectsSearchSelect">
+                                       <fieldset data-role="controlgroup" data-type="horizontal" data-mini="true" id="projectSearchSelectControlGroup">
+                                               <input type="radio" name="radio-choice" id="projects-project-select-1" value="MY PROJECT" checked="checked" onClick='projectsQueryProjectListType("MY")' />
+                                               <label for="projects-project-select-1">MY PROJECT</label>
+                                               <input type="radio" name="radio-choice" id="projects-project-select-2" value="ALL PROJECT" onClick='projectsQueryProjectListType("ALL")'/>
+                                               <label for="projects-project-select-2">ALL PROJECT</label>
+                                               
+                                               <input type="radio" name="radio-choice" id="projects-project-select-3" value="GIT PROJECT" onClick='projectsQueryProjectListType("GIT")' />
+                                               <label for="projects-project-select-3">GIT PROJECT</label>
+                                               <input type="radio" name="radio-choice" id="projects-project-select-4" value="BINARY PROJECT" onClick='projectsQueryProjectListType("BINARY")' />
+                                               <label for="projects-project-select-4">BINARY PROJECT</label>
+                                       </fieldset>
+                               </div>
+                               <br>
+                               <div id="projects-project-list">
+                               </div>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="projects-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->
+
+       <div data-role="page" id="build" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <div>
+                                       <div data-role="fieldcontain" style="text-align: center; font-size: 14px;">
+                                               <select id="select-distribution"  data-native-menu="false" onchange="buildQueryProjectList()">
+                                               </select>
+                                       </div>
+                               </div>
+                               <div data-role="collapsible" data-collapsed="false"  style="width: auto;" >
+                                       <h3>Git project</h3>
+                                       <div align="right" style="font-size: 10px">
+                                               <a href="#" data-role="button" data-inline="true" data-mini="true" onClick='buildBuildProject("build")'>Build</a>
+                                               <a href="#" data-role="button" data-inline="true" data-mini="true" onClick='buildBuildProject("resolve")'>Resolve</a>
+                                       </div>
+                                       <div data-role="content">
+                                               <table class="projectTableStyle" style="font-size: 14px" id="projectTable">
+                                               </table>
+                                       </div>
+                               </div>
+                               <div data-role="collapsible" data-collapsed="false">
+                                       <h3>Binary project</h3>
+                                       <div data-role="content">
+                                               <table class="projectTableStyle" style="font-size: 14px" id="binaryProjectTable">
+                                               </table>
+                                       </div>
+                               </div>
+                               <!--
+                               <div data-role="collapsible" data-collapsed="false">
+                                       <h3>Binary project batch upload</h3>
+                                       <div data-role="content">
+                                               <input id="buildBatchFileUploadPath" align="right" type="file" webkitdirectory multiple data-inline="true" />
+                                               <input id="buildBatchFileRegister" align="right" type="button" value="Register" data-mini="true" data-inline="true" />
+                                               <ul id="buildBatchFileList"</ul>
+                                       </div>
+                               </div>
+                               -->
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="build-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->
+
+       <div data-role="page" id="jobs" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <div id="jobDivDistribution" data-role="fieldcontain" style="text-align: center; font-size: 14px;">
+                                       <select id="jobSelectDistribution" date-mini="true" data-native-menu="false" onchange="jobsSearchSelected()">
+                                       </select>
+                               </div>
+                               <br/>
+                               <div class="ui-grid-a">
+                                       <div id="jobSearchSelect" class="ui-block-a">
+                                               <fieldset data-role="controlgroup" data-type="horizontal" data-mini="true">
+                                                       <form>
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-1" class="jobSearch" value="ALL" checked="checked" />
+                                                               <label for="search-radio-choice-1">ALL</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-2" class="jobSearch" value="JOBID"  />
+                                                               <label for="search-radio-choice-2">JOB ID</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-3" class="jobSearch" value="USER"  />
+                                                               <label for="search-radio-choice-3">USER</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-4" class="jobSearch" value="GROUP"  />
+                                                               <label for="search-radio-choice-4">GROUP</label>
+               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-5" class="jobSearch" value="PROJECT"  />
+                                                               <label for="search-radio-choice-5">PROJECT</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="radio-choice-6" class="jobSearch" value="DATE"  />
+                                                               <label for="radio-choice-6">DATE</label>
+                                                       </form>
+                                               </fieldset>
+                                       </div>
+                                       <div id="jobStatusSelect" class="ui-block-b" style="text-align:right">
+                                               <fieldset data-role="controlgroup" data-type="horizontal" data-mini="true">
+                                                       <form>
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-1" class="jobSearch" value="ALL" checked="checked" />
+                                                               <label for="search-radio-choice-1">ALL</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-2" class="jobSearch" value="SUCCESS"  />
+                                                               <label for="search-radio-choice-2">SUCCESS</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-3" class="jobSearch" value="WORKING"  />
+                                                               <label for="search-radio-choice-3">WORKING</label>
+                                                               
+                                                               <input type="radio" name="radio-choice" id="search-radio-choice-4" class="jobSearch" value="ERROR"  />
+                                                               <label for="search-radio-choice-4">ERROR</label>
+                                                       </form>
+       
+                                               </fieldset>
+                                       </div>
+                               </div>
+
+                               <div id="jobDivSearchInput" >
+                                       <input type="search" name="search-mini" id="jobSearchInputText" autocomplete="off" value="" data-mini="true" />
+                                       <a href="#" onClick="searchJobInput()" data-role="button" data-mini="true"  data-inline="true">Search</a>
+                                               
+                                       <ul data-role="listview" id="jobSearchList" data-inset="true">
+                                       </ul>
+                               </div>
+                               <div id="jobDivSearchDate" >
+                                       <input type="date" name="date" id="jobSearchDate" autocomplete="off" data-mini="true" data-inline="true" data-options='{"mode": "flipbox","noButtonFocusMode": true}' />
+                                       <a href="#" onClick="searchJobDate()" data-role="button" data-mini="true"  data-inline="true">Search</a>
+                               </div>
+                               <br>
+
+                               <ul id="jobList" data-role="listview">
+                               </ul>
+                               <br>
+
+                               <button id="moreJobList" onClick="queryJobList()" data-mini="true">MORE</button>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="jobs-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->
+
+    <div data-role="page" id="log">
+       <table id="logTable" style="border: #000000 1px solid; font-size:9pt">
+       </table> 
+       <div data-role="controlgroup" data-type="horizontal">
+               <input type="button" value="More" onClick=moreLog() / > 
+               <input type="button" value="Stop" onClick=stopLog() / > 
+       </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="adminUser" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <h2>User information</h2>
+                               <div>
+                               <table class="imagetable" style="font-size: 14px" id="adminUserTable">
+                               </table>
+                               </div>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="adminUser-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->
+       
+       <div data-role="page" id="adminUserModifyPopup" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Modify User</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <label for="popup:modifyUserName"> User name </label>
+                               <input type="text" id="popup:modifyUserName"/> 
+                               <br>
+                               <label for="popup:modifyUserEmail"> Email </label>
+                               <input type="text" id="popup:modifyUserEmail"/> 
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="popup:modifyUserGroup"> Group </label>
+                                       <br>
+                                       <select id="popup:modifyUserGroup">
+                                       </select>
+                               </div>
+                               <br>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=#adminUser onClick="adminUserModifyPopupModify()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminGroup" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <h2>Group information</h2>
+                               <div align="right" style="font-size: 10px">
+                                       <a href="#adminGroupAddPopup" data-role="button" data-rel="dialog"  data-inline="true" data-icon="plus"> Add group </a>
+                               </div>
+                               <div data-role="content" class="container">
+                                       <table class="imagetable" style="font-size: 14px" id="groupTable">
+                                       </table>
+                               </div>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="adminGroup-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->            
+                       
+       <div data-role="page" id="adminServer" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary">
+                               <h2>Server information</h2>
+                               <div align="right" style="font-size: 10px">
+                                       <a href="#adminServerAddServerInfo" data-role="button" data-rel="dialog" data-inline="true" data-icon="plus"> Add server config </a>
+                               </div>
+                               <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false">
+                                       <h2> Server info </h2>
+                                       <ul data-role="listview" id="adminServer-ServerInfo"> 
+                                       </ul>
+                               </div>  
+                               <div align="right" style="font-size: 10px">
+                                       <a href="#adminServerAddSupportedOs" data-role="button" data-rel="dialog" data-inline="true" data-icon="plus"> Add supported os</a>
+                                       <a href="#adminServerAddOSCategory" data-role="button" data-rel="dialog" data-inline="true" data-icon="plus"> Add os category</a>
+                                       <a href="#adminServerRemoveOSCategory" data-role="button" data-rel="dialog" data-inline="true" data-icon="minus"> Remove os category</a>
+                               </div>
+                               <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false">
+                                       <h2> Supported OS </h2>
+                                       <ul data-role="listview" id="adminServer-SupportedOS"> 
+                                       </ul>
+                               </div>  
+                               <div align="right" style="font-size: 10px">
+                                       <a href="#adminServerAddRemoteBuildServer" data-role="button" data-rel="dialog" data-inline="true" data-icon="plus"> Add remote build server </a>
+                               </div>  
+                               <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false">
+                                       <h2> Remote build server </h2>
+                                       <ul data-role="listview" id="adminServer-RemoteBuildServer"> 
+                                       </ul>
+                               </div>  
+                       </div><!--/content-primary -->
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="adminServer-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->            
+
+       <div data-role="page" id="adminProject" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary" >
+                               <h2>Project information</h2>
+                               <div>
+                                       <div data-role="fieldcontain" style="text-align: center; font-size: 14px;">
+                                               <select id="adminProjectDistributionSelect" data-native-menu="false" onchange="adminProjectSetProjectInfo()">
+                                               </select>
+                                       </div>
+                               </div>
+                               <div>
+                                       <div style="margin-left: 20px; margin-right: 20px; margin-top: 10px">
+                                               <div data-role="collapsible" data-theme="b" data-content-theme="c" data-collapsed="false" > 
+                                                       <h2> Git project </h2>
+                                                       <div align="right" style="font-size: 10px">
+                                                               <a href="#addGitProject"  data-role="button" data-rel="dialog"  data-inline="true" data-icon="plus"> Add git project</a>
+                                                       </div>
+                                                       <br> 
+                                                       <table class="imagetable" id="adminProjectTable" style="font-size: 14px">
+                                                       </table>
+                                               </div>
+                                               <br>
+                                               <div data-role="collapsible" data-theme="b" data-content-theme="c" data-collapsed="false" > 
+                                                       <h2> Binary project </h2>
+                                                       <div align="right" style="font-size: 10px">
+                                                               <a href="#addBinaryProject"  data-role="button"data-rel="dialog"  data-inline="true" data-icon="plus"> Add binary project</a>
+                                                       </div>
+                                                       <table class="imagetable" id="adminBinaryProjectTable" style="font-size: 14px">
+                                                       </table>
+                                               </div>
+                                       </div>
+                               </div>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="adminProject-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->            
+
+       <div data-role="page" id="adminDistribution" class="type-interior">
+        <div data-role="header" data-theme="a">                                                        
+            <a href=#index data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
+            <h1>DIBS 2.0</h1>
+            <div class="sessionInfo">
+            </div>  
+        </div><!-- /header -->
+
+               <div data-role="content" >
+                       <div class="content-primary" >
+                               <h2>Distribution information</h2>
+                               <div>
+                                       <div data-role="fieldcontain" style="text-align: center; font-size: 14px;">
+                                               <select id="adminDistributionSelect" data-native-menu="false" onchange="adminDistributionSetInfo()">
+                                               </select>
+                                       </div>
+                                       <div align="right" style="font-size: 10px">
+                                               <a href="javascript:adminDistributionFullBuild()" data-role="button" data-inline="true" data-icon="gear"> Full build</a>
+                                       </div>
+                                       <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false" > 
+                                               <h2> Package server url </h2>
+                                               <p id="adminDistribution:packageServerUrl" style="font-size: 14px"> </p>
+                                       </div>
+                                       <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false" > 
+                                               <h2> Package server address </h2>
+                                               <p id="adminDistribution:packageServerAddress" style="font-size: 14px"> </p>
+                                       </div>
+                                       <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false" > 
+                                               <h2> Status </h2>
+                                               <p id="adminDistribution:distributionStatus" style="font-size: 14px"> </p>
+                                       </div>
+                                       <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false" > 
+                                               <h2> Description </h2>
+                                               <p id="adminDistribution:distributionDescription" style="font-size: 14px"> </p>
+                                       </div>
+                                       <div data-role="collapsible" data-theme="c" data-content-theme="d" data-collapsed="false" >
+                                               <h2> Sync package server </h2>
+                                               <div id="adminDistribution-SyncPackageServer">
+                                               </div>
+                                       </div>  
+                                       <br> 
+                                       <div align="right" style="font-size: 10px">
+                                               <a href="#addDistribution" data-role="button" data-rel="dialog" data-inline="true" data-icon="plus"> Add distribution</a>
+                                               <a href="#modifyDistribution" data-role="button" data-rel="dialog" data-inline="true" data-icon="gear"> Modify distribution</a>
+                                               <a href="javascript:adminDistributionRemove()" data-role="button" data-rel="dialog" data-inline="true" data-icon="minus"> Remove distribution</a>
+                                       </div>
+                               </div>
+                       </div><!--/content-primary -->
+
+                       <div class="content-secondary">
+                               <ul data-role="listview" id="adminDistribution-navigationBar">
+                               </ul>
+                       </div>
+               </div><!-- /content -->
+       </div><!-- /page -->            
+
+       <div data-role="page" id="addDistribution" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Add Distribution</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminDistributionAddPopup-DistirubtionName"> Distirbution name </label>
+                               <input type="text" id="adminDistributionAddPopup-DistirubtionName"/>
+                               <br>
+                               <label for="adminDistributionAddPopup-PackageServerUrl"> Package server url </label>
+                               <input type="text" id="adminDistributionAddPopup-PackageServerUrl"/>
+                               <br>
+                               <label for="adminDistributionAddPopup-PackageServerAddress"> Package server address </label>
+                               <input type="text" id="adminDistributionAddPopup-PackageServerAddress"/>
+                               <br>
+                               <label for="adminDistributionAddPopup-DistributionStatus"> Distribution status </label>
+                               <select id="adminDistributionAddPopup-DistributionStatus">
+                                       <option value="OPEN" selected="selected">OPEN</option>
+                                       <option value="CLOSE">CLOSE</option>
+                               </select>
+                               <br>
+                               <label for="adminDistributionAddPopup-DistributionDescription"> Description </label>
+                               <input type="text" id="adminDistributionAddPopup-DistributionDescription"/>
+                               <br>
+                               <div>
+                                       <h3> Sync package server </h3>
+                                       <label for="adminDistributionAddPopup-SyncPackageServer-Url"> Url </label>
+                                       <input type="text" id="adminDistributionAddPopup-SyncPackageServer-Url"/>
+                                       <label for="adminDistributionAddPopup-SyncPackageServer-period"> Period </label>
+                                       <input type="text" id="adminDistributionAddPopup-SyncPackageServer-period"/>
+                                       <label for="adminDistributionAddPopup-SyncPackageServer-Description"> Description </label>
+                                       <input type="text" id="adminDistributionAddPopup-SyncPackageServer-Description"/>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminDistributionAdd()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="modifyDistribution" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Modofy Distribution</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminDistributionModifyPopup-PackageServerUrl"> Package server url </label>
+                               <input type="text" id="adminDistributionModifyPopup-PackageServerUrl"/>
+                               <br>
+                               <label for="adminDistributionModifyPopup-PackageServerAddress"> Package server address </label>
+                               <input type="text" id="adminDistributionModifyPopup-PackageServerAddress"/>
+                               <br>
+                               <label for="adminDistributionModifyPopup-Status"> Distribution status </label>
+                               <select id="adminDistributionModifyPopup-Status">
+                               </select>
+                               <br>
+                               <label for="adminDistributionModifyPopup-Description"> Description </label>
+                               <input type="text" id="adminDistributionModifyPopup-Description"/>
+                               <br>
+                               <div>
+                                       <h3> Sync package server </h3>
+                                       <label for="adminDistributionModifyPopup-SyncPackageServer-Url"> Url </label>
+                                       <input type="text" id="adminDistributionModifyPopup-SyncPackageServer-Url"/>
+                                       <label for="adminDistributionModifyPopup-SyncPackageServer-Period"> Period </label>
+                                       <input type="text" id="adminDistributionModifyPopup-SyncPackageServer-Period"/>
+                                       <label for="adminDistributionModifyPopup-SyncPackageServer-Description"> Description </label>
+                                       <input type="text" id="adminDistributionModifyPopup-SyncPackageServer-Description"/>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminDistributionModify()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div>
+       
+       <div data-role="page" id="addGitProject" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Add Git Project</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <label for="popup:addGitProjectName"> Project name </label>
+                               <input type="text" id="popup:addGitProjectName"/>
+                               <br>
+                               <label for="popup:addGitProjectPassword"> Project password </label>
+                               <input type="text" id="popup:addGitProjectPassword"/>
+                               <br>
+                               <label for="popup:addGitAddress"> Git address </label>
+                               <input type="text" id="popup:addGitAddress"/>
+                               <br>
+                               <label for="popup:addGitBranch"> Git Branch </label>
+                               <input type="text" id="popup:addGitBranch"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <fieldset data-role="controlgroup" data-mini="true" id="popup:addGitProjectOs">
+                                       </fieldset>
+                                       <br>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#adminProject" onClick="adminProjectAddGitProject()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="addBinaryProject" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Add Binary Project</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <label for="popup:addBinaryProjectName"> Project name </label>
+                               <input type="text" id="popup:addBinaryProjectName"/>
+                               <br>
+                               <label for="popup:addBinaryProjectPassword"> Project password</label>
+                               <input type="text" id="popup:addBinaryProjectPassword"/>
+                               <br>
+                               <label for="popup:addBinaryPackageName"> Pakcage name</label>
+                               <input type="text" id="popup:addBinaryPackageName"/>
+                               <div data-role="fieldcontain">
+                                       <fieldset data-role="controlgroup" data-mini="true" id="popup:addBinaryProjectOs">
+                                       </fieldset>
+                                       <br>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminProjectAddBinaryProject()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="modifyBinaryProject" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Modify Project</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <input type="hidden" id="popup:modifyBinaryOldProjectName" disabled="disabled"/> 
+                               <br>
+                               <label for="popup:modifyBinaryNewProjectName"> New Project name </label>
+                               <input type="text" id="popup:modifyBinaryNewProjectName"/> 
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="popup:modifyBinaryProjectType"> Project type </label>
+                                       <br>
+                                       <select id="popup:modifyBinaryProjectType" disabled="disabled">
+                                               <option value="git">Git</option>
+                                               <option value="binary" selected="selected">Binary</option>
+                                       </select>
+                               </div>
+                               <br>
+                               <label for="popup:modifyBinaryProjectPassword"> Project password</label>
+                               <input type="text" id="popup:modifyBinaryProjectPassword"/>
+                               <br>
+                               <label for="popup:modifyBinaryPackageName"> Pakcage name</label>
+                               <input type="text" id="popup:modifyBinaryPackageName"/>
+                               <div data-role="fieldcontain">
+                                       <fieldset data-role="controlgroup" data-mini="true" id="popup:modifyBinaryProjectOs">
+                                       </fieldset>
+                                       <br>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminProjectModfyBinaryProject()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="modifyGitProject" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Modify Project</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <input type="hidden" id="popup:modifyGitOldProjectName" disabled="disabled"/> 
+                               <br>
+                               <label for="popup:modifyGitNewProjectName"> New Project name </label>
+                               <input type="text" id="popup:modifyGitNewProjectName"/> 
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="popup:modifyGitProjectType"> Project type </label>
+                                       <br>
+                                       <select id="popup:modifyGitProjectType" disabled="disabled">
+                                               <option value="git" selected="selected">Git</option>
+                                               <option value="binary">Binary</option>
+                                       </select>
+                               </div>
+                               <br>
+                               <label for="popup:modifyGitProjectPassword"> Project password</label>
+                               <input type="text" id="popup:modifyGitProjectPassword"/>
+                               <br>
+                               <label for="popup:modifyGitProjectAddress"> Git address </label>
+                               <input type="text" id="popup:modifyGitProjectAddress"/>
+                               <br>
+                               <label for="popup:modifyGitProjectBranch"> Git branch</label>
+                               <input type="text" id="popup:modifyGitProjectBranch"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <fieldset data-role="controlgroup" data-mini="true" id="popup:modifyGitProjectOs">
+                                       </fieldset>
+                                       <br>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminProjectModfyGitProject()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminGroupAddPopup" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Add Group</h1>
+               </div>
+               <div data-role="content">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminGroupAddPopup-Name"> Group name </label>
+                               <input type="text" id="adminGroupAddPopup-Name"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="adminGroupAddPopup-Admin"> Admin Flag </label>
+                                       <br>
+                                       <select id="adminGroupAddPopup-Admin">
+                                               <option value="TRUE">True</option>
+                                               <option value="FALSE" selected="selected">False</option>
+                                       </select>
+                               </div>
+                               <br>
+                               <label for="adminGroupAddPopup-Description"> Description </label>
+                               <input type="text" id="adminGroupAddPopup-Description"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <fieldset data-role="controlgroup" data-mini="true" id="popup:addProjectCheckbox">
+                                       </fieldset>
+                                       <br>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminGroupAddGroup()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="adminGroupModifyPopup" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>modify Group</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <input type="hidden" id="adminGroupModifyPopup-Name"/>
+                               <label for="adminGroupModifyPopup-NewName"> New group name </label>
+                               <input type="text" id="adminGroupModifyPopup-NewName"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="adminGroupModifyPopup-Admin"> Admin Flag </label>
+                                       <br>
+                                       <select id="adminGroupModifyPopup-Admin">
+                                       </select>
+                               </div>
+                               <br>
+                               <label for="adminGroupModifyPopup-Description"> Description </label>
+                               <input type="text" id="adminGroupModifyPopup-Description"/>
+                               <br>
+                               <div>
+                                       <fieldset data-role="controlgroup" data-mini="true" data-role="fieldcontain" id="popup:modifyProjectSelect">
+                                       </fieldset>
+                                       <br>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminGroupModifyGroup()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="adminServerAddRemoteBuildServer" style="height: 800px; width: 800px">
+               <div data-role="header" >
+                       <h1>Add remote build server</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminServer-AddRemoteBuildServer-Address"> Server address </label>
+                               <input type="text" id="adminServer-AddRemoteBuildServer-Address"/>
+                               <br>
+                               <label for="adminServer-AddRemoteBuildServer-Description"> Server description</label>
+                               <input type="text" id="adminServer-AddRemoteBuildServer-Description"/>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminServerAddRemoteBuildServer()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="adminServerModifyRemoteBuildServer" style="height: 800px; width: 800px"> <div data-role="header" >
+                       <h1>Modify server </h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <input type="hidden" id="adminServer-modifyRemoteBuildServer-OldAddress"/>
+                               <br>
+                               <label for="adminServer-modifyRemoteBuildServer-newAddress"> New server address </label>
+                               <input type="text" id="adminServer-modifyRemoteBuildServer-newAddress"/>
+                               <br>
+                               <label for="adminServer-modifyRemoteBuildServer-description"> Description </label>
+                               <input type="text" id="adminServer-modifyRemoteBuildServer-description"/>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminServerModifyRemoteBuildServer()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+                       <a href=# onClick="adminServerRemoveRemoteBuildServer()" data-role="button" data-inline="true" data-icon="minus">Delete</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="userModifyPopup" style="height: 800px; width: 800px"> 
+               <div data-role="header" >
+                       <h1>User information</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <label for="popup-user-info-email">Email</label>
+                               <input type="text" id="popup-user-info-email" disabled="disabled"/>
+                               <br>
+                               <label for="popup-user-info-name">Name</label>
+                               <input type="text" id="popup-user-info-name"/>
+                               <br>
+                               <label for="popup-user-info-password">Password</label>
+                               <input type="password" id="popup-user-info-password"/>
+                               <br>
+                               <label for="popup-user-info-password-confirm">Password confirmation</label>
+                               <input type="password" id="popup-user-info-password-confirm"/>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="userModifyUserInfo()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+       
+       <div data-role="page" id="adminServerAddSupportedOs" style="height: 800px; width: 800px"> 
+               <div data-role="header" >
+                       <h1>Add supported os</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminServer-AddSupportedOs-OsName">Supported os name</label>
+                               <input type="text" id="adminServer-AddSupportedOs-OsName"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="adminServer-AddSupportedOs-OsCategory"> Os category </label>
+                                       <br>
+                                       <select id="adminServer-AddSupportedOs-OsCategory">
+                                       </select>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminServerAddSupportedOs()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminServerModifySupportedOS" style="height: 800px; width: 800px"> 
+               <div data-role="header" >
+                       <h1>Modify supported os</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <input type="hidden" id="adminServer-ModifySupportedOs-OldOsName" disabled="disabled"/>
+                               <label for="adminServer-ModifySupportedOs-OsName">Supported os name</label>
+                               <input type="text" id="adminServer-MoidfySupportedOs-OsName"/>
+                               <br>
+                               <div data-role="fieldcontain">
+                                       <label for="adminServer-ModifySupportedOs-OsCategory"> Os category </label>
+                                       <br>
+                                       <select id="adminServer-ModifySupportedOs-OsCategory">
+                                       </select>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminServerRemoveSupportedOS()" data-role="button" data-inline="true" data-icon="minus">Remove</a>
+                       <a href="#" onClick="adminServerModifySupportedOS()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminServerAddOSCategory" style="height: 800px; width: 800px"> 
+               <div data-role="header" >
+                       <h1>Add os category</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminServer-AddOsCategory-Name">OS category name</label>
+                               <input type="text" id="adminServer-AddOsCategory-Name"/>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminServerAddOSCategory()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminServerRemoveOSCategory" style="height: 800px; width: 800px"> 
+               <div data-role="header" >
+                       <h1>Add os category</h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <div data-role="fieldcontain">
+                                       <label for="adminServer-RemoveOSCategory-CategorySelect"> Os category </label>
+                                       <br>
+                                       <select id="adminServer-RemoveOSCategory-CategorySelect">
+                                       </select>
+                               </div>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href="#" onClick="adminServerRemoveOSCategory()" data-role="button" data-inline="true" data-icon="minus">Delete</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminServerAddServerInfo" style="height: 800px; width: 800px"> <div data-role="header" >
+                       <h1>Add server config </h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminServer-addServerInfo-property"> Property</label>
+                               <input type="text" id="adminServer-addServerInfo-property"/>
+                               <br>
+                               <label for="adminServer-addServerInfo-value"> Value </label>
+                               <input type="text" id="adminServer-addServerInfo-value"/>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminServerAddServerInfo()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+               </div>
+       </div><!-- /page -->
+
+       <div data-role="page" id="adminServerModifyServerInfo" style="height: 800px; width: 800px"> <div data-role="header" >
+                       <h1>Modify server config </h1>
+               </div>
+               <div data-role="content" data-role="fieldcontain">
+                       <form method="post" style="font-size: 12px">
+                               <label for="adminServer-modifyServerInfo-property"> Property</label>
+                               <input type="text" id="adminServer-modifyServerInfo-property" disabled="disabled"/>
+                               <br>
+                               <label for="adminServer-modifyServerInfo-value"> Value </label>
+                               <input type="text" id="adminServer-modifyServerInfo-value"/>
+                       </form>
+               </div>
+               <div align="right" style="font-size: 10px">
+                       <a href=# onClick="adminServerModifyServerInfo()" data-role="button" data-inline="true" data-icon="gear">Save</a>
+                       <a href=# onClick="adminServerRemoveServerInfo()" data-role="button" data-inline="true" data-icon="minus">Delete</a>
+               </div>
+       </div><!-- /page -->
+
+</body>
+
+       <script src="javascripts/post-process.js"></script>
+</html>
diff --git a/dibs-web/public/javascripts/admin-distribution-add.js b/dibs-web/public/javascripts/admin-distribution-add.js
new file mode 100644 (file)
index 0000000..f648638
--- /dev/null
@@ -0,0 +1,62 @@
+/* 
+ admin-distribution-add.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminDistributionAdd() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var name = document.getElementById("adminDistributionAddPopup-DistirubtionName").value;
+       var url = document.getElementById("adminDistributionAddPopup-PackageServerUrl").value;
+       var address = document.getElementById("adminDistributionAddPopup-PackageServerAddress").value;
+       var description = document.getElementById("adminDistributionAddPopup-DistributionDescription").value;
+       var distStatus = $("#adminDistributionAddPopup-DistributionStatus option:selected").val();
+
+       var sync_pkg_svr_url = document.getElementById("adminDistributionAddPopup-SyncPackageServer-Url").value;
+       var sync_pkg_svr_period = document.getElementById("adminDistributionAddPopup-SyncPackageServer-period").value;
+       var sync_pkg_svr_description = document.getElementById("adminDistributionAddPopup-SyncPackageServer-Description").value;
+
+       if(name == "" || url == "" || address == ""){
+               alert("You must input full data");
+               return;
+       }
+
+       changeInfoItem = {"DistributionName":name, "URL":url, "Address":address, "DistStatus":distStatus, "Description":description, "SyncPkgSvrUrl":sync_pkg_svr_url, "SyncPkgSvrPeriod":sync_pkg_svr_period, "SyncPkgSvrDescription":sync_pkg_svr_description};
+       changeInfoList.push(changeInfoItem);
+       
+       addDistribution(changeInfoList, function () {
+               document.getElementById("adminDistributionAddPopup-DistirubtionName").value = "";
+               document.getElementById("adminDistributionAddPopup-PackageServerUrl").value = "";
+               document.getElementById("adminDistributionAddPopup-PackageServerAddress").value = "";
+               document.getElementById("adminDistributionAddPopup-DistributionDescription").value = "";
+               document.getElementById("adminDistributionAddPopup-SyncPackageServer-Url").value = "";
+               document.getElementById("adminDistributionAddPopup-SyncPackageServer-period").value = "";
+               document.getElementById("adminDistributionAddPopup-SyncPackageServer-Description").value = "";
+
+               $.mobile.changePage("#adminDistribution"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-distribution-modify.js b/dibs-web/public/javascripts/admin-distribution-modify.js
new file mode 100644 (file)
index 0000000..5c5c293
--- /dev/null
@@ -0,0 +1,110 @@
+/* 
+ admin-distribution-modify.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminDistributionModifyPopupInit() {
+       var distName = $("#adminDistributionSelect option:selected").val();
+       var packageServerUrl = document.getElementById("adminDistribution:packageServerUrl").innerHTML;
+       var packageServeraddress = document.getElementById("adminDistribution:packageServerAddress").innerHTML;
+       var serverStatusText = document.getElementById("adminDistribution:distributionStatus").innerHTML;
+       var serverDescription = document.getElementById("adminDistribution:distributionDescription").innerHTML;
+
+       var syncPkgSvrUrl = document.getElementById("adminDistribution-SyncPackageServer-Url").innerHTML;
+       var syncPkgSvrPeriod = document.getElementById("adminDistribution-SyncPackageServer-period").innerHTML;
+       var syncPkgSvrDescription = document.getElementById("adminDistribution-SyncPackageServer-Description").innerHTML;
+
+       if (syncPkgSvrUrl) {
+               syncPkgSvrUrl = syncPkgSvrUrl.replace("Package server url : ", "");
+       } else {
+               syncPkgSvrUrl = ""
+       }
+
+       if (syncPkgSvrPeriod) {
+               syncPkgSvrPeriod = syncPkgSvrPeriod.replace("Period : ", "");
+       } else {
+               syncPkgSvrPeriod = ""
+       }
+       if (syncPkgSvrDescription) {
+               syncPkgSvrDescription = syncPkgSvrDescription.replace("Description : ", "");
+       } else {
+               syncPkgSvrDescription = ""
+       }
+
+       document.getElementById('adminDistributionModifyPopup-PackageServerUrl').value = packageServerUrl;
+       document.getElementById('adminDistributionModifyPopup-PackageServerAddress').value = packageServeraddress;
+       document.getElementById('adminDistributionModifyPopup-Description').value = serverDescription;
+       document.getElementById('adminDistributionModifyPopup-SyncPackageServer-Url').value = syncPkgSvrUrl;
+       document.getElementById('adminDistributionModifyPopup-SyncPackageServer-Period').value = syncPkgSvrPeriod;
+       document.getElementById('adminDistributionModifyPopup-SyncPackageServer-Description').value = syncPkgSvrDescription;
+
+       $("#adminDistributionModifyPopup-Status").empty();
+       var option; 
+       if(serverStatusText.toUpperCase() == "OPEN") {
+               option = '<option value="OPEN" selected="selected">OPEN</option>';
+       } else {
+               option = '<option value="OPEN">OPEN</option>';
+       }
+       $("#adminDistributionModifyPopup-Status").append(option);
+       
+       if(serverStatusText.toUpperCase() == "CLOSE") {
+               option = '<option value="CLOSE" selected="selected">CLOSE</option>';
+       } else {
+               option = '<option value="CLOSE">FALSE</option>';
+       }
+       $("#adminDistributionModifyPopup-Status").append(option);
+       $("#adminDistributionModifyPopup-Status").selectmenu("refresh");
+}
+
+function adminDistributionModify() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var distName = $("#adminDistributionSelect option:selected").val();
+       var url = document.getElementById("adminDistributionModifyPopup-PackageServerUrl").value;
+       var address = document.getElementById("adminDistributionModifyPopup-PackageServerAddress").value;
+       var description = document.getElementById("adminDistributionModifyPopup-Description").value;
+       var distStatus = $("#adminDistributionModifyPopup-Status option:selected").val();
+       var syncPkgSvrUrl = document.getElementById("adminDistributionModifyPopup-SyncPackageServer-Url").value;
+       var syncPkgSvrPeriod = document.getElementById("adminDistributionModifyPopup-SyncPackageServer-Period").value;
+       var syncPkgSvrDescription = document.getElementById("adminDistributionModifyPopup-SyncPackageServer-Description").value;
+
+       if(distName == "" || url == "" || address == ""){
+               alert("You must input full data");
+               return;
+       }
+
+       if(distStatus == "") {
+               distStatus = "OPEN";
+       }
+
+       changeInfoItem = {"DistributionName":distName, "URL":url, "Address":address, "DistStatus":distStatus, "Description":description, "SyncPkgSvrUrl":syncPkgSvrUrl, "SyncPkgSvrPeriod":syncPkgSvrPeriod, "SyncPkgSvrDescription":syncPkgSvrDescription};
+       changeInfoList.push(changeInfoItem);
+       
+       modifyDistribution( changeInfoList, function () {
+               $.mobile.changePage("#adminDistribution"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-distribution.js b/dibs-web/public/javascripts/admin-distribution.js
new file mode 100644 (file)
index 0000000..12e112b
--- /dev/null
@@ -0,0 +1,130 @@
+/* 
+ admin-distribution.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminDistributionInit() {
+       queryAllDistribution( function (xml) {
+               var oldDistName = $("#adminDistributionSelect option:selected").val();
+               var find = false;
+               var distributionList = $(xml).find("Data").find("DistributionName");
+
+               // remove old select options
+               $("#adminDistributionSelect").empty();
+
+               distributionList.each(function(){
+                       var name = $(this).text();
+       
+                       if( oldDistName == name ) {
+                               $("#adminDistributionSelect").append("<option value=\'"+name+"\' selected=\"selected\">"+name+"</option>");
+                               find = true;
+                               
+                       } else {
+                               $("#adminDistributionSelect").append("<option value=\'"+name+"\'>"+name+"</option>");
+                       }
+               });
+       
+               /* default distribution selection */
+               if(!find) {
+                       $("#adminDistributionSelect option:eq(0)").attr("selected", "selected");
+               }
+
+               $("#adminDistributionSelect").selectmenu('refresh');
+
+               // set distribution info
+               adminDistributionSetInfo();
+       });
+}
+
+function adminDistributionSetInfo() {
+       var distName = $("#adminDistributionSelect option:selected").val();
+
+       queryDistributionInfo( distName, function (xml) {
+               var data = $(xml).find("Data").find("DistributionInfo");
+               var syncPackageServer = $(xml).find("Data").find("SyncPackageServer");
+               var name = data.find("DistributionName").text();
+               var url = data.find("PackageServerUrl").text();
+               var address = data.find("PackageServerAddress").text();
+               var distStatus = data.find("Status").text();
+               var distDescription = data.find("Description").text();
+
+               $("#adminDistribution\\:packageServerUrl").text(url);
+               $("#adminDistribution\\:packageServerAddress").text(address);
+               $("#adminDistribution\\:distributionStatus").text(distStatus);
+               $("#adminDistribution\\:distributionDescription").text(distDescription);
+
+               adminDistributionInitSyncPackageServer(syncPackageServer);
+       });
+}
+
+function adminDistributionRemove() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var distName = $("#adminDistributionSelect option:selected").val();
+
+       changeInfoItem = {"DistributionName":distName};
+       changeInfoList.push(changeInfoItem);
+       
+       var r=confirm("Distribution ["+distName+"] will be removed!!!");
+       if (r==false)
+       {
+               return;
+       }
+
+       removeDistribution( changeInfoList, function (xml) {
+               $.mobile.changePage("#adminDistribution"); 
+       });
+}
+
+function adminDistributionInitSyncPackageServer(serverInfo){
+       $("#adminDistribution-SyncPackageServer").empty();
+
+       var info = '<h3 style="font-size: 16px" id="adminDistribution-SyncPackageServer-Url">Package server url : '+serverInfo.find("Url").text()+'</h3>';
+       info += '<p style="font-size: 14px" id="adminDistribution-SyncPackageServer-period">Period : '+serverInfo.find("Period").text()+'</p>';
+       info += '<p style="font-size: 14px" id="adminDistribution-SyncPackageServer-Description">Description : '+serverInfo.find("Description").text()+'</p>';
+               
+       $("#adminDistribution-SyncPackageServer").append(info);
+}
+
+function adminDistributionFullBuild() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var distName = $("#adminDistributionSelect option:selected").val();
+
+       changeInfoItem = {"DistributionName":distName};
+       changeInfoList.push(changeInfoItem);
+       
+       var r=confirm("Distribution ["+distName+"] fullbuild will be started!!! it takes several time");
+       if (r==false)
+       {
+               return;
+       }
+
+       fullBuildDistribution( changeInfoList, function (xml) {
+               $.mobile.changePage("#adminDistribution"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-group-add.js b/dibs-web/public/javascripts/admin-group-add.js
new file mode 100644 (file)
index 0000000..60c7a16
--- /dev/null
@@ -0,0 +1,101 @@
+/* 
+ admin-group-add.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminGroupAddInit() {
+       document.getElementById('adminGroupAddPopup-Name').value = "";
+       document.getElementById('adminGroupAddPopup-Description').value = "";
+
+       queryAllProject( function(xml) {
+               var fullProjectList = $(xml).find("Data").find("Project");
+
+               adminGroupAddGenerateProjectSelect(fullProjectList);
+       });
+}
+
+function adminGroupAddGenerateProjectSelect(projectList) {
+       fieldset = document.getElementById('popup:addProjectCheckbox');
+
+       /* remove all table rows */
+       while(fieldset.hasChildNodes())
+       {
+               fieldset.removeChild(fieldset.firstChild);
+       }
+
+       legend = document.createElement('legend');
+       legend.innerHTML = "Project list";
+       fieldset.appendChild(legend);
+
+       projectList.each(function(){
+               var projectName = $(this).find("Name").text();
+               var projectId = $(this).find("Id").text();
+               var projectDistName = $(this).find("DistName").text();
+
+               var input = document.createElement('input');
+               input.type = 'checkbox';
+               input.id = 'popup:addGroupProjectCheckbox:'+projectId;
+               input.name = 'popup:addGroupProjectCheckbox';
+               input.value = projectName;
+
+               var label = document.createElement('label');
+               label.setAttribute('for', 'popup:addGroupProjectCheckbox:'+projectId);
+               label.innerHTML = projectName + "[" + projectDistName + "]";
+               
+               fieldset.appendChild(input);
+               fieldset.appendChild(label);
+       });
+
+       $("[name='popup\\:addGroupProjectCheckbox']").checkboxradio();
+}
+
+function adminGroupAddGroup() {
+       var selectArray = document.getElementsByName('popup:addGroupProjectCheckbox');
+       var groupName = document.getElementById('adminGroupAddPopup-Name').value;
+       var adminFlag = $("#adminGroupAddPopup-Admin option:selected").val();
+       var description = document.getElementById('adminGroupAddPopup-Description').value;
+       var selectProjectIdList = "";
+       var changeInfoList = [];
+       
+       for(var i = 0; i < selectArray.length; i++) {
+               if (selectArray[i].checked == true) {
+                       var projectId = selectArray[i].id.split(":")[2];
+                       selectProjectIdList = selectProjectIdList + "," + projectId;
+               }
+       }
+
+       if(selectProjectIdList.length > 0) {
+               selectProjectIdList = selectProjectIdList.substring(1,selectProjectIdList.length);
+       }
+               
+       changeItem = {"GroupName" : groupName, "AdminFlag":adminFlag, "Description":description, "ProjectList" : selectProjectIdList};
+       changeInfoList.push(changeItem);
+
+       addGroup(changeInfoList, function() {
+               $.mobile.changePage("#adminGroup"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-group-modify.js b/dibs-web/public/javascripts/admin-group-modify.js
new file mode 100644 (file)
index 0000000..17ed56e
--- /dev/null
@@ -0,0 +1,129 @@
+/* 
+ admin-group-modify.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminGroupModifyInit() {
+       var index = localStorage.groupTableIndex;
+       var groupName = document.getElementById("groupTableName:"+index).innerHTML;
+       var description = document.getElementById("groupTableDescription:"+index).innerHTML;
+       var adminFlagText = document.getElementById("groupTableAdminFlag:"+index).innerHTML;
+
+       document.getElementById('adminGroupModifyPopup-Name').value = groupName;
+       document.getElementById('adminGroupModifyPopup-NewName').value = groupName;
+       document.getElementById('adminGroupModifyPopup-Description').value = description;
+       $("#adminGroupModifyPopup-Admin").empty();
+       var option; 
+       if(adminFlagText.toUpperCase() == "TRUE") {
+               option = '<option value="TRUE" selected="selected">TRUE</option>';
+       } else {
+               option = '<option value="TRUE">TRUE</option>';
+       }
+       $("#adminGroupModifyPopup-Admin").append(option);
+       
+       if(adminFlagText.toUpperCase() == "FALSE") {
+               option = '<option value="FALSE" selected="selected">FALSE</option>';
+       } else {
+               option = '<option value="FALSE">FALSE</option>';
+       }
+       $("#adminGroupModifyPopup-Admin").append(option);
+       $("#adminGroupModifyPopup-Admin").selectmenu("refresh");
+
+       queryGroupInfo(groupName, function(xml) {
+               var fullProjectList = $(xml).find("Data").find("Project");
+               var projectIdList = $(xml).find("Data").find("Group").find("ProjectList").text().split(",");
+
+               adminGroupModifyGenerateProjectSelect(fullProjectList, projectIdList);
+       });
+}
+
+function adminGroupModifyGenerateProjectSelect(fullProjectList, projectIdList) {
+       fieldset = document.getElementById('popup:modifyProjectSelect');
+       /* remove all table rows */
+       while(fieldset.hasChildNodes())
+       {
+               fieldset.removeChild(fieldset.firstChild);
+       }
+
+       legend = document.createElement('legend');
+       legend.innerHTML = "Project list";
+       fieldset.appendChild(legend);
+
+       fullProjectList.each(function(){
+               var projectName = $(this).find("Name").text();
+               var projectId = $(this).find("Id").text();
+               var projectDistName = $(this).find("DistName").text();
+
+               var input = document.createElement('input');
+               input.type = 'checkbox';
+               input.id = 'popup:modifyProjectCheckbox:'+projectId;
+               input.name = 'popup:modifyProjectCheckbox';
+               input.value = projectName;
+
+               if(contains(projectIdList, projectId))
+               {
+                       input.setAttribute('checked', 'checked');
+               }
+
+               var label = document.createElement('label');
+               label.setAttribute('for', 'popup:modifyProjectCheckbox:'+projectId);
+               label.innerHTML = projectName + "[" + projectDistName + "]";
+               
+               fieldset.appendChild(input);
+               fieldset.appendChild(label);
+       });
+
+       $("[name='popup\\:modifyProjectCheckbox']").checkboxradio();
+}
+
+function adminGroupModifyGroup() {
+       var selectArray = document.getElementsByName('popup:modifyProjectCheckbox');
+       var oldGroupName = document.getElementById('adminGroupModifyPopup-Name').value;
+       var groupName = document.getElementById('adminGroupModifyPopup-NewName').value;
+       var description = document.getElementById('adminGroupModifyPopup-Description').value;
+       var adminFlag = $("#adminGroupModifyPopup-Admin option:selected").val();
+       var selectProjectIdList = "";
+       var changeInfoList = [];
+       
+       for(var i = 0; i < selectArray.length; i++) {
+               if (selectArray[i].checked == true) {
+                       var projectId = selectArray[i].id.split(":")[2];
+                       selectProjectIdList = selectProjectIdList + "," + projectId;
+               }
+       }
+
+       if(selectProjectIdList.length > 0) {
+               selectProjectIdList = selectProjectIdList.substring(1,selectProjectIdList.length);
+       }
+               
+       changeItem = {"GroupName" : oldGroupName, "NewGroupName":groupName, "AdminFlag":adminFlag, "Description":description, "ProjectList" : selectProjectIdList};
+       changeInfoList.push(changeItem);
+
+       changeGroup(changeInfoList, function() {
+               $.mobile.changePage("#adminGroup"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-group.js b/dibs-web/public/javascripts/admin-group.js
new file mode 100644 (file)
index 0000000..6f2104b
--- /dev/null
@@ -0,0 +1,165 @@
+/* 
+ admin-group.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminGroupInit() {
+       adminGroupInitTable();
+
+       queryAllGroup( function(xml) {
+               var header = $(xml).find("Header");
+               var groupList = $(xml).find("Data").find("Group");
+
+               adminGroupFillTableInfo(groupList);
+       });
+}
+
+function adminGroupInitTable() {
+       var groupTable = document.getElementById("groupTable");
+
+       /* remove all table rows */
+       while(groupTable.hasChildNodes())
+       {
+               groupTable.removeChild(groupTable.firstChild);
+       }
+}
+
+function adminGroupFillTableInfo(groupList) {
+       var groupTable = document.getElementById("groupTable");
+
+       /* remove all table rows */
+       while(groupTable.hasChildNodes())
+       {
+               groupTable.removeChild(groupTable.firstChild);
+       }
+
+       /* create table header */
+       var row = groupTable.insertRow(-1);
+       var tableHeader = "<tr><th> Group name </th><th> Project list </th><th> Admin </th><th> Description </th><th> Modify </th><th> Delete </th></tr>";
+       
+       $("#groupTable").append(tableHeader);
+
+       var index = 2;
+
+       groupList.each(function(){
+               var row = groupTable.insertRow(-1);
+               var cell;
+               var groupName = $(this).find("GroupName").text();
+               var adminFlag = $(this).find("AdminFlag").text();
+               var description = $(this).find("Description").text();
+               var projectList = $(this).find("AccessableProject");
+
+               row.setAttribute('id', 'table:'+index);
+
+               cell = row.insertCell(-1);
+               cell.setAttribute('id', 'groupTableName:'+index);
+               cell.innerHTML = groupName
+
+               cell = row.insertCell(-1);
+               div = adminGroupGenerateProjectListCell(projectList);
+               cell.appendChild(div);
+
+               cell = row.insertCell(-1);
+               cell.setAttribute('id', 'groupTableAdminFlag:'+index);
+               cell.innerHTML = adminFlag;
+
+               cell = row.insertCell(-1);
+               cell.setAttribute('id', 'groupTableDescription:'+index);
+               cell.innerHTML = description;
+
+               cell = row.insertCell(-1);
+               var button = document.createElement('a');
+               button.setAttribute('href','#adminGroupModifyPopup');
+               button.setAttribute('data-role','button');
+               button.setAttribute('data-rel','dialog');
+               button.setAttribute('onClick','adminGroupModifyPopupSetup(\"'+index+'\")');
+               button.setAttribute('class','groupTableCellButton');
+               button.innerHTML = " "
+               cell.appendChild(button);
+
+               cell = row.insertCell(-1);
+               var button = document.createElement('input');
+               button.setAttribute('type','button');
+               button.setAttribute('onClick','adminGroupRemoveGroup('+index+')');
+               button.setAttribute('class','groupTableCellButton');
+               cell.appendChild(button);
+
+               index = index + 1;
+       });
+
+       $(".groupProjectList").collapsible();
+       $(".groupTableCellButton").button();
+}
+
+function adminGroupModifyPopupSetup(index) {
+       localStorage.groupTableIndex = index;
+}
+
+function adminGroupGenerateProjectListCell(projectList) {
+       var div = document.createElement('div');
+       div.setAttribute('data-role', 'collapsible');
+       div.setAttribute('data-content-theme', 'b');
+       div.setAttribute('class', 'groupProjectList');
+       div.setAttribute('style', 'text-align: left');
+
+       var header = document.createElement('h3');
+       header.innerHTML = "Project list";
+       div.appendChild(header);
+
+       var ul = document.createElement('ul');
+
+       projectList.each(function(){
+               var projectName = $(this).find("ProjectName").text();
+               var projectDistName = $(this).find("ProjectDistribution").text();
+               var item = document.createElement('li');
+
+               item.innerHTML = projectName+"["+projectDistName+"]";
+               ul.appendChild(item);
+       });
+
+       div.appendChild(ul);
+       return div;
+}
+
+function adminGroupRemoveGroup(index) {
+       var groupName = document.getElementById("groupTableName:"+index).innerHTML;
+
+       var r=confirm("User ["+groupName+"] will be removed!!!");
+       if (r==false)
+       {
+               return;
+       }
+
+       var changeInfoList = [];
+       var changeInfoItem;
+       changeInfoItem = {"GroupName":groupName};
+       changeInfoList.push(changeInfoItem);
+
+       removeGroup(changeInfoList, function() {
+               $.mobile.changePage("#adminGroup"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-project-add.js b/dibs-web/public/javascripts/admin-project-add.js
new file mode 100644 (file)
index 0000000..7251408
--- /dev/null
@@ -0,0 +1,177 @@
+/* 
+ admin-project-add.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminProjectAddGitInit() {
+       document.getElementById("popup:addGitProjectName").value = "";
+       document.getElementById("popup:addGitProjectPassword").value = "";
+       document.getElementById("popup:addGitAddress").value = "";
+       document.getElementById("popup:addGitBranch").value = "";
+
+       queryAllOS( function (xml) {
+               var osList = $(xml).find("Data").find("OsName");
+
+               fieldset = document.getElementById('popup:addGitProjectOs');
+               /* remove all table rows */
+               while(fieldset.hasChildNodes())
+               {
+                       fieldset.removeChild(fieldset.firstChild);
+               }
+        
+               legend = document.createElement('legend');
+               legend.innerHTML = "Project os list";
+               fieldset.appendChild(legend);
+        
+               osList.each(function(){
+                       var osName = $(this).text();
+        
+                       var input = document.createElement('input');
+                       input.type = 'checkbox';
+                       input.id = 'popup:addGitProjectOsCheckbox:'+osName;
+                       input.name = 'popup:addGitProjectOsCheckbox';
+                       input.value = osName;
+                       input.setAttribute('class', 'popup:addGitProjectOsCheckbox');
+                       input.setAttribute('checked', 'checked');
+        
+                       var label = document.createElement('label');
+                       label.setAttribute('for', 'popup:addGitProjectOsCheckbox:'+osName);
+                       label.innerHTML = osName;
+                       
+                       fieldset.appendChild(input);
+                       fieldset.appendChild(label);
+               });
+        
+               $('.popup\\:addGitProjectOsCheckbox').checkboxradio();
+       });
+}
+
+function adminProjectAddBinaryInit() {
+       document.getElementById("popup:addBinaryProjectName").value = "";
+       document.getElementById("popup:addBinaryProjectPassword").value = "";
+       document.getElementById("popup:addBinaryPackageName").value = "";
+
+       queryAllOS( function (xml) {
+               var osList = $(xml).find("Data").find("OsName");
+
+               fieldset = document.getElementById('popup:addBinaryProjectOs');
+               /* remove all table rows */
+               while(fieldset.hasChildNodes())
+               {
+                       fieldset.removeChild(fieldset.firstChild);
+               }
+        
+               legend = document.createElement('legend');
+               legend.innerHTML = "Project os list";
+               fieldset.appendChild(legend);
+        
+               osList.each(function(){
+                       var osName = $(this).text();
+        
+                       var input = document.createElement('input');
+                       input.type = 'checkbox';
+                       input.id = 'popup:addBinaryProjectOsCheckbox:'+osName;
+                       input.name = 'popup:addBinaryProjectOsCheckbox';
+                       input.value = osName;
+                       input.setAttribute('class', 'popup:addBinaryProjectOsCheckbox');
+                       input.setAttribute('checked', 'checked');
+        
+                       var label = document.createElement('label');
+                       label.setAttribute('for', 'popup:addBinaryProjectOsCheckbox:'+osName);
+                       label.innerHTML = osName;
+                       
+                       fieldset.appendChild(input);
+                       fieldset.appendChild(label);
+               });
+        
+               $('.popup\\:addBinaryProjectOsCheckbox').checkboxradio();
+       });
+}
+
+function adminProjectAddGitProject() {
+       var distName = $("#adminProjectDistributionSelect option:selected").val();
+       var changeInfoList = [];
+       var changeInfoItem;
+       var type = "GIT";
+       var name = document.getElementById("popup:addGitProjectName").value;
+       var password = document.getElementById("popup:addGitProjectPassword").value;
+       var address = document.getElementById("popup:addGitAddress").value;
+       var branch = document.getElementById("popup:addGitBranch").value;
+       var selectArray = document.getElementsByName('popup:addGitProjectOsCheckbox');
+       var selectOsList = [];
+
+       for(var i = 0; i < selectArray.length; i++) {
+               if (selectArray[i].checked == true) {
+                       var osName = selectArray[i].id.split(":")[2];
+                       selectOsList.push(osName);
+               }
+       }
+
+
+       if(name == "" || password == "" || address == "" || branch == ""){
+               alert("You must input full data(Project name, Git password, Git address, Branch)");
+               return;
+       }
+
+       changeInfoItem = {"Distribution":distName, "Name":name, "ProjectType":type, "ProjectPass":password, "Address":address, "Branch":branch, "OSNameList":selectOsList.toString()};
+       changeInfoList.push(changeInfoItem);
+       
+       addProject(changeInfoList, function () {
+               $.mobile.changePage("#adminProject"); 
+       });
+}
+
+function adminProjectAddBinaryProject() {
+       var distName = $("#adminProjectDistributionSelect option:selected").val();
+       var changeInfoList = [];
+       var changeInfoItem;
+       var type = "BINARY";
+       var name = document.getElementById("popup:addBinaryProjectName").value;
+       var password = document.getElementById("popup:addBinaryProjectPassword").value;
+       var pkgName = document.getElementById("popup:addBinaryPackageName").value;
+       var selectArray = document.getElementsByName('popup:addBinaryProjectOsCheckbox');
+       var selectOsList = [];
+
+       for(var i = 0; i < selectArray.length; i++) {
+               if (selectArray[i].checked == true) {
+                       var osName = selectArray[i].id.split(":")[2];
+                       selectOsList.push(osName);
+               }
+       }
+
+       if(name == "" || pkgName == ""){
+               alert("You must input full data(Project name, Package name");
+               return;
+       }
+
+       changeInfoItem = {"Distribution":distName, "Name":name, "ProjectType":type, "ProjectPass":password, "PackageName":pkgName, "OSNameList":selectOsList.toString()};
+       changeInfoList.push(changeInfoItem);
+       
+       addProject(changeInfoList, function () {
+               $.mobile.changePage("#adminProject"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-project-modify.js b/dibs-web/public/javascripts/admin-project-modify.js
new file mode 100644 (file)
index 0000000..420d093
--- /dev/null
@@ -0,0 +1,209 @@
+/* 
+ admin-project-modify.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminProjectModifyBinaryProjectInit() {
+       var projectName = localStorage.projectName;
+       var packageName = document.getElementById('modifyBinaryPackageName:'+projectName).innerHTML;
+
+       document.getElementById('popup:modifyBinaryOldProjectName').value = projectName;
+       document.getElementById('popup:modifyBinaryNewProjectName').value = projectName;
+       document.getElementById('popup:modifyBinaryProjectPassword').value = "";
+       document.getElementById('popup:modifyBinaryPackageName').value = packageName;
+
+       queryAllOS( function (xml) {
+               var osList = $(xml).find("Data").find("OsName");
+               var selectedOsList = [];
+               var projectName = localStorage.projectName;
+       
+               var osListElement = document.getElementById('adminBINARYProjectTableOsList:'+projectName);
+               for(var i = 0; i < osListElement.childNodes.length; i++)
+               {
+                       selectedOsList.push(osListElement.childNodes[i].innerHTML);
+               }
+
+               fieldset = document.getElementById('popup:modifyBinaryProjectOs');
+               /* remove all table rows */
+               while(fieldset.hasChildNodes())
+               {
+                       fieldset.removeChild(fieldset.firstChild);
+               }
+        
+               legend = document.createElement('legend');
+               legend.innerHTML = "Project os list";
+               fieldset.appendChild(legend);
+        
+               osList.each(function(){
+                       var osName = $(this).text();
+        
+                       var input = document.createElement('input');
+                       input.type = 'checkbox';
+                       input.id = 'popup:modifyBinaryProjectOs:'+osName;
+                       input.name = 'popup:modifyBinaryProjectOs'
+                       input.value = osName;
+                       input.setAttribute('class', 'popup:modifyBinaryProjectOs');
+                       if(contains(selectedOsList, osName))
+                       {
+                               input.setAttribute('checked', 'checked');
+                       }
+        
+                       var label = document.createElement('label');
+                       label.setAttribute('for', 'popup:modifyBinaryProjectOs:'+osName);
+                       label.innerHTML = osName;
+                       
+                       fieldset.appendChild(input);
+                       fieldset.appendChild(label);
+               });
+        
+               $('.popup\\:modifyBinaryProjectOs').checkboxradio();
+       });
+}
+
+function adminProjectModifyGitProjectInit() {
+       var projectName = localStorage.projectName;
+       var projectAddress = document.getElementById('modifyGitProjectAddress:'+projectName).innerHTML;
+       var projectBranch = document.getElementById('modifyGitProjectBranch:'+projectName).innerHTML;
+
+       document.getElementById('popup:modifyGitOldProjectName').value = projectName;
+       document.getElementById('popup:modifyGitNewProjectName').value = projectName;
+       document.getElementById('popup:modifyGitProjectPassword').value = "";
+       document.getElementById('popup:modifyGitProjectAddress').value = projectAddress;
+       document.getElementById('popup:modifyGitProjectBranch').value = projectBranch;
+
+       queryAllOS( function (xml) {
+               var osList = $(xml).find("Data").find("OsName");
+               var selectedOsList = [];
+               var projectName = localStorage.projectName;
+       
+               var osListElement = document.getElementById('adminGITProjectTableOsList:'+projectName);
+               for(var i = 0; i < osListElement.childNodes.length; i++)
+               {
+                       selectedOsList.push(osListElement.childNodes[i].innerHTML);
+               }
+
+               fieldset = document.getElementById('popup:modifyGitProjectOs');
+               /* remove all table rows */
+               while(fieldset.hasChildNodes())
+               {
+                       fieldset.removeChild(fieldset.firstChild);
+               }
+        
+               legend = document.createElement('legend');
+               legend.innerHTML = "Project os list";
+               fieldset.appendChild(legend);
+        
+               osList.each(function(){
+                       var osName = $(this).text();
+        
+                       var input = document.createElement('input');
+                       input.type = 'checkbox';
+                       input.id = 'popup:modifyGitProjectOs:'+osName;
+                       input.name = 'popup:modifyGitProjectOs'
+                       input.value = osName;
+                       input.setAttribute('class', 'popup:modifyGitProjectOs');
+                       if(contains(selectedOsList, osName))
+                       {
+                               input.setAttribute('checked', 'checked');
+                       }
+        
+                       var label = document.createElement('label');
+                       label.setAttribute('for', 'popup:modifyGitProjectOs:'+osName);
+                       label.innerHTML = osName;
+                       
+                       fieldset.appendChild(input);
+                       fieldset.appendChild(label);
+               });
+        
+               $('.popup\\:modifyGitProjectOs').checkboxradio();
+       });
+}
+
+function adminProjectModfyBinaryProject() {
+       var distName = $("#adminProjectDistributionSelect option:selected").val();
+       var changeInfoList = [];
+       var changeInfoItem;
+       var oldProjectName = document.getElementById('popup:modifyBinaryOldProjectName').value;
+       var newProjectName = document.getElementById('popup:modifyBinaryNewProjectName').value;
+       var projectType = document.getElementById('popup:modifyBinaryProjectType').value;
+       var projectPassword = document.getElementById('popup:modifyBinaryProjectPassword').value;
+       var packageName = document.getElementById('popup:modifyBinaryPackageName').value;
+       var selectArray = document.getElementsByName('popup:modifyBinaryProjectOs');
+       var selectOsList = [];
+
+       for(var i = 0; i < selectArray.length; i++) {
+               if (selectArray[i].checked == true) {
+                       var osName = selectArray[i].id.split(":")[2];
+                       selectOsList.push(osName);
+               }
+       }
+
+       if(oldProjectName == "" || newProjectName == "" || projectPassword == "" || projectType == "" || packageName == ""){
+               alert("You must input full data");
+               return;
+       }
+               
+       changeInfoItem = {"Distribution":distName, "Name":oldProjectName, "NewProjectName":newProjectName, "ProjectType":projectType, "ProjectPass":projectPassword, "PackageName":packageName, "OSNameList":selectOsList.toString()};
+       changeInfoList.push(changeInfoItem);
+
+       modifyProject(changeInfoList, function () {
+               $.mobile.changePage("#adminProject"); 
+       });
+}
+
+function adminProjectModfyGitProject() {
+       var distName = $("#adminProjectDistributionSelect option:selected").val();
+       var changeInfoList = [];
+       var changeInfoItem;
+       var oldProjectName = document.getElementById('popup:modifyGitOldProjectName').value;
+       var newProjectName = document.getElementById('popup:modifyGitNewProjectName').value;
+       var projectType = document.getElementById('popup:modifyGitProjectType').value;
+       var projectPassword = document.getElementById('popup:modifyGitProjectPassword').value;
+       var projectAddress = document.getElementById('popup:modifyGitProjectAddress').value;
+       var projectBranch = document.getElementById('popup:modifyGitProjectBranch').value;
+       var selectArray = document.getElementsByName('popup:modifyGitProjectOs');
+       var selectOsList = [];
+
+       for(var i = 0; i < selectArray.length; i++) {
+               if (selectArray[i].checked == true) {
+                       var osName = selectArray[i].id.split(":")[2];
+                       selectOsList.push(osName);
+               }
+       }
+
+       if(oldProjectName == "" || newProjectName == "" || projectPassword == "" || projectType == "" || projectAddress == "" || projectBranch == ""){
+               alert("You must input full data");
+               return;
+       }
+               
+       changeInfoItem = {"Distribution":distName, "Name":oldProjectName, "NewProjectName":newProjectName, "ProjectType":projectType, "ProjectPass":projectPassword, "ProjectAddress":projectAddress, "ProjectBranch":projectBranch, "OSNameList":selectOsList.toString()};
+       changeInfoList.push(changeInfoItem);
+
+       modifyProject(changeInfoList, function () {
+               $.mobile.changePage("#adminProject"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-project.js b/dibs-web/public/javascripts/admin-project.js
new file mode 100644 (file)
index 0000000..03e06b7
--- /dev/null
@@ -0,0 +1,255 @@
+/* 
+ admin-project.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminProjectInit() {
+       queryAllDistribution( function (xml) {
+               var oldDistName = $("#adminProjectDistributionSelect option:selected").val();
+               var find = false;
+               var distributionList = $(xml).find("Data").find("DistributionName");
+
+               // remove old select options
+               $("#adminProjectDistributionSelect").empty();
+
+               distributionList.each(function(){
+                       var name = $(this).text();
+       
+                       if( oldDistName == name ) {
+                               $("#adminProjectDistributionSelect").append("<option value=\'"+name+"\' selected=\"selected\">"+name+"</option>");
+                               find = true;
+                               
+                       } else {
+                               $("#adminProjectDistributionSelect").append("<option value=\'"+name+"\'>"+name+"</option>");
+                       }
+               });
+       
+               /* default distribution selection */
+               if(!find) {
+                       $("#adminProjectDistributionSelect option:eq(0)").attr("selected", "selected");
+               }
+
+               $("#adminProjectDistributionSelect").selectmenu('refresh');
+
+               // set project info
+               adminProjectSetProjectInfo();
+       });
+}
+
+function adminProjectSetProjectInfo() {
+       var distName = $("#adminProjectDistributionSelect option:selected").val();
+
+       queryProjectsInDistributionForAdmin( distName, function (xml) {
+               var projectList = $(xml).find("Data").find("Project");
+       
+               // update project info
+               adminProjectUpdateTable(projectList);
+       });
+}
+
+function popupModifyProject(projectName) {
+       localStorage.projectName = projectName;
+}
+
+function adminProjectRemoveProject(projectType, projectName ) {
+       var distName = $("#adminProjectDistributionSelect option:selected").val();
+
+       var r=confirm("Project ["+projectName+"] is removed!!!");
+       if (r==false)
+       {
+               return;
+       }
+
+       var changeInfoList = [];
+       var changeInfoItem;
+       changeInfoItem = {"Distribution":distName, "ProjectType":projectType, "Name":projectName};
+       changeInfoList.push(changeInfoItem);
+       
+       removeProject(changeInfoList, function () {
+               $.mobile.changePage("#adminProject"); 
+       });
+}
+
+function adminProjectUpdateTable(projectList) {
+       /* project table */
+       var projectTable = document.getElementById("adminProjectTable");
+
+       /* binary project table */
+       var binaryProjectTable = document.getElementById("adminBinaryProjectTable");
+
+       /* remove all table rows */
+       while(projectTable.hasChildNodes())
+       {
+               projectTable.removeChild(projectTable.firstChild);
+       }
+       while(binaryProjectTable.hasChildNodes())
+       {
+               binaryProjectTable.removeChild(binaryProjectTable.firstChild);
+       }
+
+       // Project table header
+       var tableHeader = "<tr><th>Project</th><th>Git repos</th><th>Branch</th><th>OS list</th><th>Modify</th><th>Delete</th>";
+       $("#adminProjectTable").append(tableHeader);
+
+       // Binary project table header
+       var tableHeader = "<tr><th>Project</th><th>Package name</th><th>OS list</th><th>Modify</th><th>Delete</th>";
+       $("#adminBinaryProjectTable").append(tableHeader);
+
+       var projectIdx = 1;
+       var binaryProjectIdx = 1;
+       // add project information
+       projectList.each(function(){
+               var name = $(this).find("ProjectName").text();
+               var type = $(this).find("Type").text();
+               var osList = $(this).find("OS");
+
+               if(type.toUpperCase() == "GIT")
+               {
+                       var row = projectTable.insertRow(-1);
+                       var cell;
+
+                       cell = row.insertCell(-1);
+                       cell.setAttribute('style', 'text-align: left');
+                       cell.setAttribute('id',"modifyGitProjectName:"+name);
+                       cell.innerHTML = name;
+
+                       cell = row.insertCell(-1);
+                       cell.setAttribute('style', 'text-align: left');
+                       cell.setAttribute('id',"modifyGitProjectAddress:"+name);
+                       cell.innerHTML = $(this).find("GitRepos").text();
+
+                       cell = row.insertCell(-1);
+                       cell.setAttribute('style', 'text-align: left');
+                       cell.setAttribute('id',"modifyGitProjectBranch:"+name);
+                       cell.innerHTML = $(this).find("GitBranch").text();
+
+                       cell = row.insertCell(-1);
+                       div = adminProjectApendOsCell(osList, name, "GIT");
+                       cell.appendChild(div);
+
+                       cell = row.insertCell(-1);
+                       var button = document.createElement('a');
+                       button.setAttribute('href','#modifyGitProject');
+                       button.setAttribute('data-role','button');
+                       button.setAttribute('data-rel','dialog');
+                       button.setAttribute('data-mini','true');
+                       button.setAttribute('onClick','popupModifyProject(\"'+name+'\")');
+                       button.setAttribute('class','binaryProjectTableButton');
+                       button.innerHTML = " "
+                       cell.appendChild(button);
+
+                       cell = row.insertCell(-1);
+                       var button = document.createElement('input');
+                       button.setAttribute('type','button');
+                       button.setAttribute('id','button:git:'+projectIdx+':'+name);
+                       button.setAttribute('data-mini','true');
+                       button.setAttribute('name',name);
+                       button.setAttribute('class','binaryProjectTableButton');
+                       button.setAttribute('onClick','adminProjectRemoveProject(\"GIT\"'+',\"'+name+'\"'+')');
+                       cell.appendChild(button);
+
+                       projectIdx = projectIdx + 1;
+               }
+               else if (type.toUpperCase() == "BINARY")
+               {
+                       var row = binaryProjectTable.insertRow(-1);
+                       var cell;
+
+                       cell = row.insertCell(-1);
+                       cell.setAttribute('style', 'text-align: left');
+                       cell.setAttribute('id',"modifyBinaryProjectName:"+name);
+                       cell.innerHTML = name;
+
+                       cell = row.insertCell(-1);
+                       cell.setAttribute('style', 'text-align: left');
+                       cell.setAttribute('id',"modifyBinaryPackageName:"+name);
+                       cell.innerHTML = $(this).find("PackageName").text();
+
+                       cell = row.insertCell(-1);
+                       div = adminProjectApendOsCell(osList, name, "BINARY");
+                       cell.appendChild(div);
+
+                       cell = row.insertCell(-1);
+                       var button = document.createElement('a');
+                       button.setAttribute('href','#modifyBinaryProject');
+                       button.setAttribute('data-role','button');
+                       button.setAttribute('data-inline','true');
+                       button.setAttribute('data-mini','true');
+                       button.setAttribute('data-rel','dialog');
+                       button.setAttribute('onClick','popupModifyProject(\"'+name+'\")');
+                       button.setAttribute('class','binaryProjectTableButton');
+                       cell.appendChild(button);
+
+                       cell = row.insertCell(-1);
+                       var button = document.createElement('input');
+                       button.setAttribute('type','button');
+                       button.setAttribute('class','binaryProjectTableButton');
+                       button.setAttribute('data-mini','true');
+                       button.setAttribute('name',name);
+                       button.setAttribute('onClick','adminProjectRemoveProject(\"BINARY\"'+',\"'+name+'\"'+')');
+                       cell.appendChild(button);
+
+                       binaryProjectIdx = binaryProjectIdx + 1;
+               }
+               else
+                       alert("Unknown project type");
+
+       });
+
+       $(".binaryProjectTableButton").button();
+       $(".groupProjectList").collapsible();
+}
+
+function adminProjectApendOsCell(osList, projectName, projectType) {
+
+       var div = document.createElement('div');
+
+       div.setAttribute('data-role', 'collapsible');
+       div.setAttribute('data-mini', 'true');
+       div.setAttribute('data-content-theme', 'b');
+       div.setAttribute('class', 'groupProjectList');
+
+       var header = document.createElement('h3');
+       header.innerHTML = "OS list";
+       div.appendChild(header);
+
+       var ul = document.createElement('ul');
+       ul.setAttribute('id', 'admin'+projectType+'ProjectTableOsList:'+projectName);
+
+       // if osList does not exist then just return 
+       if (osList != undefined) {
+               osList.each(function(){
+                       var item = document.createElement('li');
+                       item.innerHTML = $(this).text();
+                       ul.appendChild(item);
+               });
+       }
+
+       div.appendChild(ul);
+       return div;
+}
+
+
diff --git a/dibs-web/public/javascripts/admin-server-add.js b/dibs-web/public/javascripts/admin-server-add.js
new file mode 100644 (file)
index 0000000..18a47d2
--- /dev/null
@@ -0,0 +1,133 @@
+/* 
+ admin-server-add.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminServerAddSupportedOsInit() {
+       // Remove select option
+       $('#adminServer-AddSupportedOs-OsCategory').empty();
+
+       queryAllOSCategory(function(xml){
+               $(xml).find("Data").find("OsCategoryName").each(function(){
+                       var name = $(this).text();
+
+                       $('#adminServer-AddSupportedOs-OsCategory').append("<option value=\'"+name+"\'>"+name+"</option>");
+       
+                       $('#adminServer-AddSupportedOs-OsCategory').selectmenu('refresh');
+               });
+       });
+}
+
+function adminServerAddRemoteBuildServer() {
+       var changeInfoList = [];
+       var changeInfoItem;
+
+       var address = document.getElementById("adminServer-AddRemoteBuildServer-Address").value;
+       var description = document.getElementById("adminServer-AddRemoteBuildServer-Description").value;
+
+       if(address == ""){
+               alert("You must input server address");
+               return;
+       }
+
+       changeInfoItem = {"Address":address, "Description":description};
+       changeInfoList.push(changeInfoItem);
+       
+       addRemoteBuildServer(changeInfoList, function () {
+               document.getElementById('adminServer-AddRemoteBuildServer-Address').value = "";
+               document.getElementById('adminServer-AddRemoteBuildServer-Description').value = "";
+
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerAddSupportedOs() {
+       var changeInfoList = [];
+       var changeInfoItem;
+
+       var osName = document.getElementById("adminServer-AddSupportedOs-OsName").value;
+       var osCategory = $("#adminServer-AddSupportedOs-OsCategory option:selected").val();
+
+       if(osName == ""){
+               alert("You must input server address");
+               return;
+       }
+
+       changeInfoItem = {"Name":osName, "OsCategory":osCategory};
+       changeInfoList.push(changeInfoItem);
+       
+       addSupportedOS(changeInfoList, function () {
+               document.getElementById('adminServer-AddSupportedOs-OsName').value = "";
+
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerAddOSCategory() {
+       var changeInfoList = [];
+       var changeInfoItem;
+
+       var categoryName = document.getElementById("adminServer-AddOsCategory-Name").value;
+
+       if(categoryName == ""){
+               alert("You must input category name");
+               return;
+       }
+
+       changeInfoItem = {"Name":categoryName};
+       changeInfoList.push(changeInfoItem);
+       
+       addOSCategory(changeInfoList, function () {
+               document.getElementById('adminServer-AddOsCategory-Name').value = "";
+
+               $.mobile.changePage("#adminServer"); 
+       }); 
+} 
+
+function adminServerAddServerInfo() {
+       var property = document.getElementById('adminServer-addServerInfo-property').value;
+       var value = document.getElementById('adminServer-addServerInfo-value').value;
+       var changeInfoList = [];
+       var changeInfoItem;
+
+       if(property == ""){
+               alert("property is empty");
+               return;
+       }
+
+       if(value == ""){
+               alert("value is empty");
+               return;
+       }
+
+       changeInfoItem = {"Property":property, "Value":value};
+       changeInfoList.push(changeInfoItem);
+       
+       addServerInfo(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-server-modify.js b/dibs-web/public/javascripts/admin-server-modify.js
new file mode 100644 (file)
index 0000000..28e9c97
--- /dev/null
@@ -0,0 +1,125 @@
+/* 
+ admin-server-modify.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminServerModifyRemoteBuildServerInit() {
+       var serverAddress = localStorage.remoteBuildServerAddress;
+       var serverDescription = localStorage.remoteBuildServerDescription;
+
+       document.getElementById('adminServer-modifyRemoteBuildServer-OldAddress').value = serverAddress;
+       document.getElementById('adminServer-modifyRemoteBuildServer-newAddress').value = serverAddress;
+       document.getElementById('adminServer-modifyRemoteBuildServer-description').value = serverDescription 
+}
+
+function adminServerModifyServerInfoInit(property, value) {
+       document.getElementById('adminServer-modifyServerInfo-property').value = property;
+       document.getElementById('adminServer-modifyServerInfo-value').value = value;
+}
+
+function adminServerModifySupportedOSInit(osName, osCategory) {
+       // Remove select option
+       $('#adminServer-ModifySupportedOs-OsCategory').empty();
+
+       document.getElementById('adminServer-ModifySupportedOs-OldOsName').value = osName;
+       document.getElementById('adminServer-MoidfySupportedOs-OsName').value = osName;
+
+       queryAllOSCategory( function(xml){
+               $(xml).find("Data").find("OsCategoryName").each(function(){
+                       var name = $(this).text();
+                       var option = ""
+                       
+                       if(name == osCategory) {
+                               option = '<option value="'+name+'" selected="selected">'+name+'</option>'
+                       } else {
+                               option = '<option value="'+name+'">'+name+'</option>'
+                       }
+
+                       $('#adminServer-ModifySupportedOs-OsCategory').append(option);
+                       $('#adminServer-ModifySupportedOs-OsCategory').selectmenu("refresh");
+               });
+       });
+}
+
+function adminServerModifyRemoteBuildServer() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var serverAddress = document.getElementById('adminServer-modifyRemoteBuildServer-OldAddress').value;
+       var newServerAddress = document.getElementById('adminServer-modifyRemoteBuildServer-newAddress').value;
+       var description = document.getElementById('adminServer-modifyRemoteBuildServer-description').value;
+
+       if(serverAddress == ""){
+               alert("server address is invalid");
+               return;
+       }
+
+       changeInfoItem = {"Address":serverAddress, "NewAddress":newServerAddress, "Description":description};
+       changeInfoList.push(changeInfoItem);
+
+       modifyRemoteBuildServer(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerModifySupportedOS() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var oldOsName = document.getElementById('adminServer-ModifySupportedOs-OldOsName').value;
+       var osName = document.getElementById('adminServer-MoidfySupportedOs-OsName').value;
+       var osCategory = $("#adminServer-ModifySupportedOs-OsCategory option:selected").val();
+
+       changeInfoItem = {"Name":oldOsName, "NewName":osName, "OsCategory":osCategory};
+       changeInfoList.push(changeInfoItem);
+
+       modifySupportedOS(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerModifyServerInfo() {
+       var property = document.getElementById('adminServer-modifyServerInfo-property').value;
+       var value = document.getElementById('adminServer-modifyServerInfo-value').value;
+       var changeInfoList = [];
+       var changeInfoItem;
+
+       if(property == ""){
+               alert("property is empty");
+               return;
+       }
+
+       if(value == ""){
+               alert("value is empty");
+               return;
+       }
+
+       changeInfoItem = {"Property":property, "Value":value};
+       changeInfoList.push(changeInfoItem);
+       
+       modifyServerInfo(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-server-remove.js b/dibs-web/public/javascripts/admin-server-remove.js
new file mode 100644 (file)
index 0000000..db74a01
--- /dev/null
@@ -0,0 +1,116 @@
+/* 
+ admin-server-remove.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminServerRemoveOSCategoryInit() {
+       // Remove select option
+       $('#adminServer-RemoveOSCategory-CategorySelect').empty();
+
+       queryAllOSCategory(function(xml){
+               $(xml).find("Data").find("OsCategoryName").each(function(){
+                       var name = $(this).text();
+
+                       $('#adminServer-RemoveOSCategory-CategorySelect').append("<option value=\'"+name+"\'>"+name+"</option>");
+                       
+                       $('#adminServer-RemoveOSCategory-CategorySelect').selectmenu('refresh');
+               });
+       });
+}
+
+function adminServerRemoveOSCategory() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var osCategory = $("#adminServer-RemoveOSCategory-CategorySelect option:selected").val();
+
+       if(osCategory == ""){
+               alert("Os category is invalid");
+               return;
+       }
+
+       changeInfoItem = {"Name":osCategory};
+       changeInfoList.push(changeInfoItem);
+
+       removeOSCategory(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerRemoveSupportedOS() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var oldOsName = document.getElementById('adminServer-ModifySupportedOs-OldOsName').value;
+       var osName = document.getElementById('adminServer-MoidfySupportedOs-OsName').value;
+
+       if(oldOsName != osName ){
+               alert("Remove command must be same to original os name");
+               return;
+       }
+
+       changeInfoItem = {"Name":osName};
+       changeInfoList.push(changeInfoItem);
+
+       removeSupportedOS(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerRemoveServerInfo() {
+       var property = document.getElementById('adminServer-modifyServerInfo-property').value;
+       var changeInfoList = [];
+       var changeInfoItem;
+
+       if(property == ""){
+               alert("property is empty");
+               return;
+       }
+
+       changeInfoItem = {"Property":property};
+       changeInfoList.push(changeInfoItem);
+       
+       removeServerInfo(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
+function adminServerRemoveRemoteBuildServer() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var serverAddress = document.getElementById('adminServer-modifyRemoteBuildServer-OldAddress').value;
+
+       if(serverAddress == ""){
+               alert("server address is invalid");
+               return;
+       }
+
+       changeInfoItem = {"Address":serverAddress};
+       changeInfoList.push(changeInfoItem);
+
+       removeRemoteBuildServer(changeInfoList, function () {
+               $.mobile.changePage("#adminServer"); 
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-server.js b/dibs-web/public/javascripts/admin-server.js
new file mode 100644 (file)
index 0000000..6aae3e9
--- /dev/null
@@ -0,0 +1,109 @@
+/* 
+ admin-server.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminServerInit() {
+       $('#adminServer-RemoteBuildServer').collapsible();
+
+       queryAllServer( function (xml) {
+               var serverConfig = $(xml).find("Data").find("ServerConfig");
+               var buildServerList = $(xml).find("Data").find("RemoteBuildServer");
+               var syncPackageServerList = $(xml).find("Data").find("SyncPackageServer");
+               adminServerInitServerInfo(serverConfig);
+               adminServerRemoteInitRemoteBuildServer(buildServerList);
+       });
+
+       queryAllOS( function (xml) {
+               $("#adminServer-SupportedOS").empty();
+
+               $(xml).find("Data").find("OS").each(function(){
+                       var osName = $(this).find("OsName").text();
+                       var osCategory = $(this).find("OsCategory").text();
+
+                       var li = '<li><a href="#adminServerModifySupportedOS" ';
+                       li += 'onClick="adminServerModifySupportedOSInit(\''+osName+'\',\''+osCategory+'\')" ';
+                       li += 'data-rel="dialog">';
+                       li += '<h3>'+osName+'</h3>';
+                       li += '<p>OS category : '+osCategory+'</p>';
+                       li += '</a></li>';
+
+                       $("#adminServer-SupportedOS").append(li);
+               });
+
+               $("#adminServer-SupportedOS").listview('refresh');
+       });
+}
+
+function adminServerInitServerInfo(serverConfig){
+       $("#adminServer-ServerInfo").empty();
+
+       serverConfig.each(function(){
+               var property = $(this).find("Property").text();
+               var value = $(this).find("Value").text();
+
+               var li = '<li><a href="#adminServerModifyServerInfo" ';
+               li += 'onClick="adminServerModifyServerInfoInit(\''+property+'\',\''+value+'\')" ';
+               li += 'data-rel="dialog">';
+               li += '<p>'+property+' : '+value+'</p>';
+               li += '</a></li>';
+               $("#adminServer-ServerInfo").append(li);
+       });
+
+       $("#adminServer-ServerInfo").listview('refresh');
+}
+
+function adminServerRemoteInitRemoteBuildServer(serverList){
+       $("#adminServer-RemoteBuildServer").empty();
+
+       serverList.each(function(){
+               var address = $(this).find("Address").text();
+               var description = $(this).find("Description").text();
+
+               var li = '<li><a href="#adminServerModifyRemoteBuildServer" ';
+               li += 'onClick="popupModifyRemoteBuildServerInfo(\''+address+'\',\''+description+'\')" ';
+               li += 'data-rel="dialog">';
+               li += '<h3>'+address+'</h3>';
+               li += '<p>Description : '+$(this).find("Description").text()+'</p>';
+               li += '<br><p>Runtime infomation</p>';
+               li += '<p>Status: '+$(this).find("Status").text()+'</p>';
+               li += '<p>Supported OS: '+$(this).find("SupportedOS").text()+'</p>';
+               li += '<p>Max job count: '+$(this).find("MaxJobCount").text()+'</p>';
+               li += '<p>Working job count: '+$(this).find("WorkingJobCount").text()+'</p>';
+               li += '<p>Waiting job count: '+$(this).find("WaitingJobCount").text()+'</p>';
+               li += '</a></li>';
+                       
+               $("#adminServer-RemoteBuildServer").append(li);
+       });
+
+       $("#adminServer-RemoteBuildServer").listview('refresh');
+}
+
+function popupModifyRemoteBuildServerInfo(address, description) {
+       localStorage.remoteBuildServerAddress = address;
+       localStorage.remoteBuildServerDescription = description;
+}
+
diff --git a/dibs-web/public/javascripts/admin-user-modify.js b/dibs-web/public/javascripts/admin-user-modify.js
new file mode 100644 (file)
index 0000000..fd00e41
--- /dev/null
@@ -0,0 +1,71 @@
+/* 
+ admin-user-modify.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminUserModifyPopupInit() {
+       var index = localStorage.userTableIndex;
+       var userName = document.getElementById("userTableName:"+index).innerHTML;
+       var email = document.getElementById("userTableEmail:"+index).innerHTML;
+       var group = document.getElementById("userTableGroup:"+index).innerHTML;
+
+       document.getElementById('popup:modifyUserName').value = userName;
+       mailElement = document.getElementById('popup:modifyUserEmail');
+       mailElement.value = email;
+       mailElement.setAttribute('disabled', 'disabled');
+
+       queryAllGroup( function(xml) {
+               var groupList = $(xml).find("Data").find("GroupName");
+               
+               $("#popup\\:modifyUserGroup").empty();
+
+               groupList.each( function(){
+                       var groupName = $(this).text();
+                       if( groupName == group ) {
+                               $("#popup\\:modifyUserGroup").append("<option value=\'"+groupName+"\' selected=\"selected\">"+groupName+"</option>");
+                       } else {
+                               $("#popup\\:modifyUserGroup").append("<option value=\'"+groupName+"\'>"+groupName+"</option>");
+                       }
+
+                       $("#popup\\:modifyUserGroup").selectmenu('refresh');
+               });
+       });
+}
+
+function adminUserModifyPopupModify() {
+       var userName = document.getElementById("popup:modifyUserName").value;
+       var email = document.getElementById("popup:modifyUserEmail").value;
+       var groupName = $("#popup\\:modifyUserGroup option:selected").val();
+
+       var changeInfoList = [];
+       var changeInfoItem;
+       changeInfoItem = {"Type":"ModifyUser", "Email":email, "UserName":userName, "GroupName":groupName};
+       changeInfoList.push(changeInfoItem);
+
+       changeUser(changeInfoList, function () {
+       });
+}
+
diff --git a/dibs-web/public/javascripts/admin-user.js b/dibs-web/public/javascripts/admin-user.js
new file mode 100644 (file)
index 0000000..73acf00
--- /dev/null
@@ -0,0 +1,119 @@
+/* 
+ admin-user.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function adminUserInit() {
+       var userTable = document.getElementById("adminUserTable");
+
+       /* remove all table rows */
+       while(userTable.hasChildNodes())
+       {
+               userTable.removeChild(userTable.firstChild);
+       }
+
+       /* create table header */
+       var tableHeader = "<tr><th>User name</th><th>Email</th><th>Group</th><th>Modify</th><th>Delete</th></tr>";
+       $("#adminUserTable").append(tableHeader);
+
+       queryAllUser( function(xml) {
+               var userList = $(xml).find("Data").find("User");
+
+               adminUserFillTable(userList);
+       });
+}
+
+function adminUserFillTable(userList) {
+       var userTable = document.getElementById("adminUserTable");
+       var index = 2;
+
+       userList.each(function(idx){
+               var row = userTable.insertRow(-1);
+               var cell;
+               var userName = $(this).find("Name").text();
+               var groupName = $(this).find("GroupName").text();
+               var email = $(this).find("Email").text();
+
+               row.setAttribute('id', 'userTable:'+index);
+               cell = row.insertCell(-1);
+               cell.setAttribute('id',"userTableName:"+index);
+               cell.innerHTML = userName;
+
+               cell = row.insertCell(-1);
+               cell.setAttribute('id',"userTableEmail:"+index);
+               cell.innerHTML = email;
+
+               cell = row.insertCell(-1);
+               cell.setAttribute('id',"userTableGroup:"+index);
+               cell.innerHTML = groupName;
+
+               cell = row.insertCell(-1);
+               var button = document.createElement('a');
+               button.setAttribute('href','#adminUserModifyPopup');
+               button.setAttribute('data-role','button');
+               button.setAttribute('data-rel','dialog');
+               button.setAttribute('class','adminUserTableButton');
+               button.setAttribute('onClick','adminUserModifyPopupSetup(\"'+index+'\")');
+               button.innerHTML = " "
+               cell.appendChild(button);
+
+               cell = row.insertCell(-1);
+               var button = document.createElement('input');
+               button.setAttribute('type','button');
+               button.setAttribute('name',email);
+               button.setAttribute('class','adminUserTableButton');
+               button.setAttribute('onClick','adminUserRemoveUser('+index+')');
+               cell.appendChild(button);
+
+               index = index + 1;
+       });
+
+       $(".adminUserTableButton").button();
+}
+
+function adminUserModifyPopupSetup(index) {
+       localStorage.userTableIndex = index;
+}
+
+function adminUserRemoveUser(index) {
+       var email = document.getElementById("userTableEmail:"+index).innerHTML;
+
+       var r=confirm("User ["+email+"] is removed!!!");
+       if (r==false)
+       {
+               return;
+       }
+
+       var changeInfoList = [];
+       var changeInfoItem;
+       changeInfoItem = {"Type":"RemoveUser", "Email":email};
+       changeInfoList.push(changeInfoItem);
+
+       removeUser(changeInfoList, function () {
+               $.mobile.changePage("#adminUser");
+       });
+}
+
diff --git a/dibs-web/public/javascripts/application.js b/dibs-web/public/javascripts/application.js
new file mode 100644 (file)
index 0000000..9097d83
--- /dev/null
@@ -0,0 +1,15 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require jquery
+//= require jquery_ujs
+//= require_tree .
diff --git a/dibs-web/public/javascripts/build.js b/dibs-web/public/javascripts/build.js
new file mode 100644 (file)
index 0000000..c2efd25
--- /dev/null
@@ -0,0 +1,344 @@
+/* 
+ build.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function buildInit() {
+       if( $("#select-distribution").children().length == 0 ) {
+               queryDistribution( function(xml) {
+                       $(xml).find("Data").find("DistributionName").each(function(){
+                               var name = $(this).text();
+               
+                               $("#select-distribution").append("<option value=\'"+name+"\'>"+name+"</option>");
+                       });
+               
+                       /* default distribution selection */
+                       $("#select-distribution option:eq(0)").attr("selected", "selected");
+                       $("#select-distribution").selectmenu('refresh');
+               
+                       // query Project list
+                       buildQueryProjectList();
+            
+                       // query Running project list
+                       //buildQueryRunningProjectList();
+            
+                       // add batch file selector event
+                       //buildBatchFilePathSelector();
+               });
+       } else {
+               // query Project list
+               buildQueryProjectList();
+        
+               // query Running project list
+               //buildQueryRunningProjectList();
+        
+               // add batch file selector event
+               //buildBatchFilePathSelector();
+       }
+}
+
+function buildQueryProjectList() {
+       var distName = $("#select-distribution option:selected").val();
+
+       queryProjectsInDistribution( distName, function(xml) {
+               buildInitTable();
+               var xmlBody = $(xml).find("Data");
+               buildAddTableRow( xmlBody.find("BuildServerInfo").find("supportedOs"),
+                                        xmlBody.find("Project"),
+                                        xmlBody.find("OtherProject"));
+               buildAddBinaryTableRow( xmlBody.find("BinaryProject"),
+                                        xmlBody.find("OtherBinaryProject"));
+       });
+}
+
+function buildQueryRunningProjectList() {
+       var distName = $("#select-distribution option:selected").val();
+
+       queryRunningProjectsInfoInDistribution( distName, function(xml) {
+               var running_project = $(xml).find("RunProjectInfo");
+               running_project.each(function(){
+                       var project_name = $(this).find("ProjectName").text();
+                       var project_os = $(this).find("ProjectOs").text();
+                       var project_type = $(this).find("ProjectType").text();
+                       var project_status = $(this).find("Status").text();
+
+                       if (project_type == "GIT") {
+                               var cell = document.getElementById("buildGitProjectTable"+":"+project_name+':'+project_os);
+
+                               if(cell){
+                                       cell.setAttribute('bgcolor', '#fbff00');
+                               }
+                       } 
+               });
+       });
+}
+
+function buildSelectAll(element) {
+       var checkboxes = document.getElementsByName(element.id);
+       var checked = element.checked;
+       for(var i in checkboxes) {
+               if(!checkboxes[i].disabled) { 
+                       checkboxes[i].checked = checked;
+               } 
+       }
+}
+
+function contains(a, obj) {
+       for (var i = 0; i < a.length; i++) {
+               if (a[i] == obj) {
+                       return true; 
+               }
+       }
+       return false; 
+}
+
+function buildInitTable() {
+       /* project table */
+       var projectTable = document.getElementById("projectTable");
+       
+       /* binary project table */
+       var binaryProjectTable = document.getElementById("binaryProjectTable");
+       
+       /* remove all table rows */
+       while(projectTable.hasChildNodes())
+       {
+               projectTable.removeChild(projectTable.firstChild);
+       }
+       while(binaryProjectTable.hasChildNodes())
+       {
+               binaryProjectTable.removeChild(binaryProjectTable.firstChild);
+       }
+}
+
+function buildAddTableRow(supportedOs, projectList, otherProjectList) {
+       // Table header
+       var idx = 0;
+       var tableHeader = "";
+       var osArray = new Array();
+       var projectTable = document.getElementById("projectTable");
+
+       // Project table header
+       tableHeader = "<tr><th>Project</th>";
+       supportedOs.each(function(){
+               var osName = $(this).text();
+               tableHeader = tableHeader + "<th>"+osName+"</th>";
+
+               osArray[idx] = osName;
+               idx++;
+       });
+
+       tableHeader = tableHeader + "<th>ALL</th></tr>";
+       $("#projectTable").append(tableHeader);
+
+       // table row - projectList
+       var index = 2;
+
+       projectList.each(function(){
+               var name = $(this).find("ProjectName").text();
+               var osLists = $(this).find("OsList").text();
+               var osList = osLists.split(",");
+       
+               var row = projectTable.insertRow(-1);
+               
+               var cell = row.insertCell(0);
+               cell.setAttribute('style', 'text-align: left');
+               cell.setAttribute('bgcolor', '#dcddc0');
+               cell.innerHTML = name;
+               
+               for (i=0;i<osArray.length;i++)
+               {
+                       var cell = row.insertCell(-1);
+                       var os = osArray[i];
+       
+                       cell.setAttribute('id', "buildGitProjectTable"+":"+name+":"+os);
+                       cell.setAttribute('style', 'text-align: center');
+                       cell.setAttribute('bgcolor', '#dcddc0');
+       
+                       var buttonnode = document.createElement('input');
+                       buttonnode.setAttribute('type','checkbox');
+                       buttonnode.setAttribute('id',"table"+":"+name+':'+os);
+                       buttonnode.setAttribute('name','projectBuildCheckbox'+":"+name);
+                       buttonnode.setAttribute('class','projectTableBuildButton');
+                       cell.appendChild(buttonnode);
+
+                       if(!contains(osList, os))
+                       {
+                               buttonnode.setAttribute('disabled','disabled');
+                       }
+               }
+       
+               /* append all checkbox */
+               var cell = row.insertCell(-1);
+               cell.setAttribute('style', 'text-align: center');
+               cell.setAttribute('bgcolor', '#dcddc0');
+       
+               var buttonnode = document.createElement('input');
+               buttonnode.setAttribute('type','checkbox');
+               buttonnode.setAttribute('id','projectBuildCheckbox'+":"+name);
+               buttonnode.setAttribute('name','all-checkbox');
+               buttonnode.setAttribute('class','projectTableAllButton');
+               buttonnode.setAttribute('onClick','buildSelectAll(this)');
+               cell.appendChild(buttonnode);
+       });
+
+       otherProjectList.each(function(){
+               var name =  $(this).find("ProjectName").text();
+               var row = projectTable.insertRow(-1);
+               
+               var cell = row.insertCell(0);
+               cell.setAttribute('style', 'text-align: left');
+               cell.setAttribute('bgcolor', '#c0c0c0');
+               cell.innerHTML = name;
+       
+               /* add empty cell for status */
+               for (i=0;i<osArray.length;i++)
+               {
+                       cell = row.insertCell(-1);
+                       cell.setAttribute('id', "table"+":"+name+"-"+osArray[i]);
+                       cell.setAttribute('style', 'text-align: left');
+                       cell.setAttribute('bgcolor', '#c0c0c0');
+                       cell.innerHTML = ""; 
+               }
+       
+               /* add empty cell for all*/
+               cell = row.insertCell(-1);
+               cell.setAttribute('style', 'text-align: left');
+               cell.setAttribute('bgcolor', '#c0c0c0');
+               cell.innerHTML = "";
+       });
+}
+
+function buildAddBinaryTableRow(binaryProjectList, otherProjectList) {
+       var binaryProjectTable = document.getElementById("binaryProjectTable");
+       var row = binaryProjectTable.insertRow(-1);
+       var thCell = document.createElement('th');
+       thCell.innerHTML = "Project";
+       row.appendChild(thCell);
+       thCell = document.createElement('th');
+       thCell.innerHTML = "Package name";
+       row.appendChild(thCell);
+       thCell = document.createElement('th');
+       thCell.innerHTML = "Register";
+       row.appendChild(thCell);
+
+       /* insert binary project in binary project table */
+       binaryProjectList.each(function(){
+               var name =  $(this).find("ProjectName").text();
+               var packageName =  $(this).find("PackageName").text();
+               var row = '<tr><td bgcolor="#dcddc0" style="text-align:left">'+name+'</td>';
+               row += '<td bgcolor="#dcddc0" style="text-align:left">' + packageName + '</td>'
+               row += '<td bgcolor="#dcddc0" style="text-align:left"><a href="upload.html" onClick="buildUploadBinaryName(\'' +name+'\')" class="binary_project_button" data-role="button" data-ajax="false" data-mini="true">REGISTER</a>';
+               row += '</tr>'
+               
+               $("#binaryProjectTable tr:last").after(row);
+       });
+
+       otherProjectList.each(function(){
+               var name =  $(this).find("ProjectName").text();
+               var packageName =  $(this).find("PackageName").text();
+               var row = binaryProjectTable.insertRow(-1);
+               
+               /* add project name */
+               var cell = row.insertCell(0);
+               cell.setAttribute('style', 'text-align: left');
+               cell.setAttribute('bgcolor', '#c0c0c0');
+               cell.innerHTML = name;
+       
+               /* add package name */
+               cell = row.insertCell(-1);
+               cell.setAttribute('style', 'text-align: left');
+               cell.setAttribute('bgcolor', '#c0c0c0');
+               cell.innerHTML = packageName; 
+       
+               /* add empty cell for register */
+               cell = row.insertCell(-1);
+               cell.setAttribute('style', 'text-align: left');
+               cell.setAttribute('bgcolor', '#c0c0c0');
+               cell.innerHTML = "";
+       });
+
+       $('.binary_project_button').button();
+       $('.binary_project_button').popupWindow({ 
+               height:200, 
+               width:400, 
+               top:50, 
+               left:50 
+       });
+}
+
+function buildBuildProject(type) {
+       var distName = $("#select-distribution option:selected").val();
+       var buildProjectList = [];
+
+       //var node_list = document.getElementsByTagName('input');
+       var node_list = $("#build input")
+       for (var i = 0; i < node_list.length; i++) {
+               var node = node_list[i];
+       
+               if (node.getAttribute('type') == "checkbox") {
+                       if (node.checked == true) {
+                               if (node.getAttribute('name') != "all-checkbox") {
+                                       var prjName = node.id.split(":")[1];
+                                       var osName = node.id.split(":")[2];
+                                       var buildData = { "distribution":distName, "buildType":type, "projectName" : prjName, "os" : osName };
+                                       buildProjectList.push(buildData);
+                               }
+                       }
+               }
+       }
+       
+       buildProject(buildProjectList, function () {
+               $.mobile.changePage("#jobs"); 
+       });
+}
+
+function buildUploadBinaryName(project_name) {
+       localStorage.distibutionName = $("#select-distribution option:selected").val();
+       localStorage.uploadBinaryProjectName = project_name;
+}
+
+function buildBatchFilePathSelector() {
+       var files, file, extension;
+       var filePath = document.getElementById("buildBatchFileUploadPath");
+       var filePathOutputList = document.getElementById("buildBatchFileList");
+
+       filePath.addEventListener("change", function(e) {
+           files = e.target.files;
+           filePathOutputList.innerHTML = "";
+           
+           for (var i = 0, len = files.length; i < len; i++) {
+               file = files[i];
+                       alert(file.webkitRelativePath);
+               filePathOutputList.innerHTML += "<li style='font-size:12px'>" + file.name + "</li>";
+           }
+       }, false);      
+}
+
+function buildClear() {
+       $("#select-distribution").empty();
+       
+       buildInitTable();
+}
diff --git a/dibs-web/public/javascripts/dibs-api.js b/dibs-web/public/javascripts/dibs-api.js
new file mode 100644 (file)
index 0000000..9802a71
--- /dev/null
@@ -0,0 +1,392 @@
+/* 
+ dibs-api.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+// controller: Users
+function signUp(infoList, successFunction) {
+       var url = 'users/signup';
+       postForServer(url, infoList, successFunction);
+}
+
+function queryUserInfo(successFunction) {
+       var url = 'users/query';
+       getInfoFromServer(url, successFunction);
+}
+
+function modifyUserInfo(changeInfoList, successFunction) {
+       var url = 'users/modify';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+// controller: Sessions
+function login(infoList, successFunction) {
+       var url = 'sessions/login';
+       postForServer(url, infoList, successFunction);
+}
+
+function logout() {
+       var url = 'sessions/logout';
+       deleteForServer(url, function() {
+               expireSession();
+               dibsWebClear();
+       });
+}
+
+// controller: projects
+function queryDistribution(successFunction) {
+       var url = 'projects/queryDistribution';
+       getInfoFromServer(url, successFunction);
+}
+
+// controller : projects
+function buildProject(changeInfoList, successFunction) {
+       var url = 'projects/buildProject';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function queryProjectsInDistribution(distName, successFunction) {
+       var url = 'projects/queryProjectsInDistribution/' + distName;
+       getInfoFromServer(url, successFunction);
+}
+
+function queryRunningProjectsInfoInDistribution(distName, successFunction) {
+       var url = 'projects/queryRunningProjectsInfoInDistribution/' + distName;
+       getInfoFromServer(url, successFunction);
+}
+
+function queryProjectsInfoInDistribution(distName, successFunction) {
+       var url = 'projects/queryProjectsInfoInDistribution/' + distName;
+       getInfoFromServer(url, successFunction);
+}
+
+// controller : jobs
+function queryJobsList(url, successFunction) {
+       return getInfoFromServer(url, successFunction);
+}
+function updateList(data, successFunction) {
+       var url = "jobs/update";
+       var param = $.param(data);
+       return getInfoFromServerData(url, param, successFunction);
+}
+function queryJobsLog(job_id, next_line, successFunction) {
+       var url = "jobs/log/"+ job_id + "/" + next_line;
+       getInfoFromServerNoPreProcess(url, successFunction);
+}
+function cancelJobsJobid(job_id, successFunction) {
+       var url = "jobs/cancel/"+ job_id;
+       getInfoFromServerNoPreProcess(url, successFunction);
+}
+
+// controller : admin_group
+function queryAllGroup(successFunction) {
+       var url = 'admin_group/queryAllGroup';
+       getInfoFromServer(url, successFunction);
+}
+
+function queryGroupInfo(groupName, successFunction) {
+       var url = 'admin_group/queryGroupInfo/' + groupName;
+       getInfoFromServer(url, successFunction);
+}
+
+function addGroup(changeInfoList, successFunction) {
+       var url = 'admin_group/addGroup';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeGroup(changeInfoList, successFunction) {
+       var url = 'admin_group/removeGroup';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function changeGroup(changeInfoList, successFunction) {
+       var url = 'admin_group/modifyGroup';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+// controller : admin_user
+function queryAllUser(successFunction) {
+       var url = 'admin_user/queryAllUser';
+       getInfoFromServer(url, successFunction);
+}
+
+function changeUser(changeInfoList, successFunction) {
+       var url = 'admin_user/modifyUser';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeUser(changeInfoList, successFunction) {
+       var url = 'admin_user/removeUser';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+// controller : admin_server
+function queryServerInfo(successFunction) {
+       var url = 'admin_server/queryServerInfo';
+       getInfoFromServer(url, successFunction);
+}
+
+function queryAllServer(successFunction) {
+       var url = 'admin_server/queryAllServer';
+       getInfoFromServer(url, successFunction);
+}
+
+function addRemoteBuildServer(changeInfoList, successFunction) {
+       var url = 'admin_server/addRemoteBuildServer';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeRemoteBuildServer(changeInfoList, successFunction) {
+       var url = 'admin_server/removeRemoteBuildServer';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function modifyRemoteBuildServer(changeInfoList, successFunction) {
+       var url = 'admin_server/modifyRemoteBuildServer';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function addOSCategory(changeInfoList, successFunction) {
+       var url = 'admin_server/addOsCategory';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeOSCategory(changeInfoList, successFunction) {
+       var url = 'admin_server/removeOsCategory';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function modifyOSCategory(changeInfoList, successFunction) {
+       var url = 'admin_server/modifyOsCategory';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function addSupportedOS(changeInfoList, successFunction) {
+       var url = 'admin_server/addSupportedOS';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeSupportedOS(changeInfoList, successFunction) {
+       var url = 'admin_server/removeSupportedOS';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function modifySupportedOS(changeInfoList, successFunction) {
+       var url = 'admin_server/modifySupportedOS';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function addServerInfo(changeInfoList, successFunction) {
+       var url = 'admin_server/addServerInfo';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeServerInfo(changeInfoList, successFunction) {
+       var url = 'admin_server/removeServerInfo';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function modifyServerInfo(changeInfoList, successFunction) {
+       var url = 'admin_server/modifyServerInfo';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+// controller : admin_project
+function queryAllProject(successFunction) {
+       var url = 'admin_project/queryAllProject';
+       getInfoFromServer(url, successFunction);
+}
+
+function queryProjectsInDistributionForAdmin(distName, successFunction) {
+       var url = 'admin_project/queryProjectsInDistributionForAdmin/' + distName;
+       getInfoFromServer(url, successFunction);
+}
+
+function addProject(changeInfoList, successFunction) {
+       var url = 'admin_project/addProject';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeProject(changeInfoList, successFunction) {
+       var url = 'admin_project/removeProject';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function modifyProject(changeInfoList, successFunction) {
+       var url = 'admin_project/modifyProject';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+// controller : admin_distribution
+function queryAllDistribution(successFunction) {
+       var url = 'admin_distribution/queryAllDistribution';
+       getInfoFromServer(url, successFunction);
+}
+
+function queryDistributionInfo(distName, successFunction) {
+       var url = 'admin_distribution/queryDistributionInfo/' + distName;
+       getInfoFromServer(url, successFunction);
+}
+
+function addDistribution(changeInfoList, successFunction) {
+       var url = 'admin_distribution/addDistribution';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function removeDistribution(changeInfoList, successFunction) {
+       var url = 'admin_distribution/removeDistribution';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function modifyDistribution(changeInfoList, successFunction) {
+       var url = 'admin_distribution/modifyDistribution';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+function fullBuildDistribution(changeInfoList, successFunction) {
+       var url = 'admin_distribution/fullBuildDistribution';
+       postForServer(url, changeInfoList, successFunction);
+}
+
+// controller : admin
+function queryAllOS(successFunction) {
+       var url = 'admin/queryAllOS';
+       getInfoFromServer(url, successFunction);
+}
+
+function queryAllOSCategory(successFunction) {
+       var url = 'admin/queryAllOSCategory';
+       getInfoFromServer(url, successFunction);
+}
+
+function getInfoFromServer(url, successFunction) {
+       return $.ajax({
+               url: baseUrl+url,
+               type: 'GET',
+               dataType: 'xml',
+               timeout: 10000,
+               beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner
+               complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner
+               success: function(xml) {
+                       setSessionInfo(xml);
+                       successFunction(xml);
+               },
+               error: function(jqXHR) {
+                       errorProcess(jqXHR);
+               }
+       });
+}
+
+function getInfoFromServerNoPreProcess(url, successFunction) {
+       return $.ajax({
+               url: baseUrl+url,
+               type: 'GET',
+               dataType: 'xml',
+               timeout: 10000,
+               success: function(xml) {
+                       setSessionInfo(xml);
+                       successFunction(xml);
+               },
+               error: function(jqXHR) {
+                       errorProcess(jqXHR);
+               }
+       });
+}
+
+function getInfoFromServerData(url, data, successFunction) {
+       return $.ajax({
+               url: baseUrl+url,
+               type: 'GET',
+               dataType: 'xml',
+               text: 'JSONP',
+               data: data,
+               timeout: 10000,
+               success: function(xml) {
+                       setSessionInfo(xml);
+                       successFunction(xml);
+               },
+               error: function(jqXHR) {
+                       errorProcess(jqXHR);
+               }
+       });
+}
+
+function postForServer(url, changeInfoList, successFunction) {
+       $.ajax({
+               url: baseUrl+url,
+               type: 'POST',
+               data: JSON.stringify({ ChangeInfoList: changeInfoList }),
+               dataType: 'json',
+               contentType: "application/json; charset=utf-8",
+               timeout: 10000,
+               beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner
+               complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner
+               success: function(xml) {
+                       successFunction(xml);
+               },
+               error: function(jqXHR) {
+                       errorProcess(jqXHR);
+               }
+       });
+}
+
+function deleteForServer(url, successFunction) {
+       $.ajax({
+               url: baseUrl+url,
+               type: 'DELETE',
+               async: false,
+               cache: false,
+               dataType: 'xml',
+               timeout: 1000,
+               beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner
+               complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner
+               success: function(xml) {
+                       expireSession();
+                       dibsWebClear();
+               },
+               error: function(jqXHR) {
+                       errorProcess(jqXHR);
+               }
+       });
+}
+
+function errorProcess(jqXHR){
+       switch (parseInt(jqXHR.status)) {
+               case 401:       
+                       expireSession();
+                       break;
+               case 406:       
+                       alert("Internal server error : " + jqXHR.responseText);
+                       break;
+               case 0:
+                       console.error("Error response status : "+jqXHR.status);
+                       break;
+               default:
+                       console.error("Error response status : "+jqXHR.status);
+                       alert("Server error : "+jqXHR.status);
+                       break;
+       }
+}
diff --git a/dibs-web/public/javascripts/jobs.js b/dibs-web/public/javascripts/jobs.js
new file mode 100644 (file)
index 0000000..cde6c98
--- /dev/null
@@ -0,0 +1,695 @@
+/* 
+ jobs.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+var suggestion_list = new Array();
+var update_ajax;
+var request_list = new Array();
+var request_idx = 0;
+
+$(function() {
+       $('#jobSearchSelect input[type="radio"]').checkboxradio().click(function() {
+               jobsSearchSelected();
+       });
+
+       $('#jobStatusSelect input[type="radio"]').checkboxradio().click(function() {
+               jobsStatusSelected();
+       });
+
+       $("#jobSearchInputText").on("input", function(e) {
+               var selectedValue = $('#jobSearchSelect').find("input[type='radio']:checked").val();
+               switch(selectedValue) {
+                       case "GROUP":
+                       case "PROJECT":
+                               suggestJobSearchList($(this).val());
+                               break;
+                       default:
+                               return;
+               }
+       });
+
+       $('#jobSearchInputText').keypress(function() {
+               if(event.keyCode == '13') {
+                       searchJobInput();
+               }
+       });
+
+       $('#jobSearchDate').keypress(function() {
+               if(event.keyCode == '13') {
+                       searchJobDate();
+               }
+       });
+});
+
+function jobsInit() {
+       jobQueryDistribution();
+}
+
+function jobsSearchSelected() {
+       clearSuggestJobSearchList();
+
+       var selectedValue = $('#jobSearchSelect').find("input[type='radio']:checked").val();
+       switch(selectedValue) {
+               case "ALL":
+                       selectJobAll();
+                       break;
+               case "JOBID":
+                       selectJobId();
+                       break;
+               case "USER":
+                       selectUser();
+                       break;
+               case "GROUP":
+                       selectGroup();
+                       break;
+               case "PROJECT":
+                       selectProject();
+                       break;
+               case "DATE":
+                       selectDate();
+                       break;
+               default:
+                       alert("Sorry. Please, report bug.");
+                       break;
+       }
+}
+
+function jobsStatusSelected() {
+       var selectedValue = $('#jobStatusSelect').find("input[type='radio']:checked").val();
+       switch(selectedValue) {
+               case "ALL":
+                       jobsSearchSelected();
+                       break;
+               case "SUCCESS":
+                       jobsSearchSelected();
+                       break;
+               case "WORKING":
+                       jobsSearchSelected();
+                       break;
+               case "ERROR":
+                       jobsSearchSelected();
+                       break;
+               default:
+                       alert("Sorry. Please, report bug.");
+                       break;
+       }
+}
+
+function searchJobInput() {
+       var searchText = $("#jobSearchInputText").val()
+       if(searchText.length > 0) {
+               searchJob(searchText);
+       }
+}
+
+function searchJobDate() {
+       var searchText = $("#jobSearchDate").val()
+       if(searchText.length > 0) {
+               searchJob(searchText);
+       }
+}
+
+function searchJob(searchText) {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       var selectedValue = $('#jobSearchSelect').find("input[type='radio']:checked").val();
+       switch(selectedValue) {
+               case "ALL":
+                       alert("Can't search on ALL!!");
+                       break;
+               case "JOBID":
+                       queryJobListJobId(distribution, searchText);
+                       break;
+               case "USER":
+                       queryJobListUserName(distribution, searchText);
+                       break;
+               case "GROUP":
+                       queryJobListUserGroup(distribution, searchText);
+                       break;
+               case "PROJECT":
+                       queryJobListProject(distribution, searchText);
+                       break;
+               case "DATE":
+                       queryJobListDate(distribution, searchText);
+                       break;
+               default:
+                       alert("Sorry. Please, report bug.");
+                       break;
+       }
+}
+
+function selectJobAll() {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       $("#jobDivSearchDate").hide();
+       $("#jobDivSearchInput").hide();
+       queryJobListAll(distribution);
+}
+
+function selectJobId() {
+       $("#jobDivSearchDate").hide();
+       $("#jobDivSearchInput").show();
+       $("#jobSearchInputText").val("").textinput();
+       clearJobList();
+}
+
+function selectUser() {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       $("#jobDivSearchDate").hide();
+       $("#jobDivSearchInput").show();
+
+       var name = sessionStorage.sessionInfoName;
+       $("#jobSearchInputText").val(name).textinput();
+
+       queryJobListUserName(distribution, name);
+}
+
+function selectGroup() {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       $("#jobDivSearchDate").hide();
+       $("#jobDivSearchInput").show();
+
+       var group = sessionStorage.sessionInfoGroup;
+       $("#jobSearchInputText").val(group).textinput();
+
+       jobsQueryGroupList("JOBS");
+
+       queryJobListUserGroup(distribution, group);
+}
+
+function selectProject() {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       $("#jobDivSearchDate").hide();
+       $("#jobDivSearchInput").show();
+       clearJobList();
+
+       $("#jobSearchInputText").val("").textinput();
+
+       jobsQueryProjectsList(distribution);
+}
+
+function selectDate() {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       var today = new Date();
+       var yyyy = today.getFullYear();
+       var mm = today.getMonth()+1; //January is 0!
+       var dd = today.getDate(); //January is 0!
+       if(dd<10) {
+               dd='0'+dd;
+       } 
+       if(mm<10) {
+               mm='0'+mm;
+       } 
+
+       var date = yyyy+'-'+mm+'-'+dd;
+       $('#jobSearchDate').val(date);
+
+       $("#jobDivSearchInput").hide();
+       $("#jobDivSearchDate").show();
+       clearJobList();
+       queryJobListDate(distribution, date);
+}
+
+function clearJobList() {
+       $("#jobList").empty();
+}
+
+function queryJobListAll(distribution) {
+       queryJobListByButton("all", "", distribution, "LATEST");
+}
+
+function queryJobListJobId(distribution, jobId) {
+       queryJobListByButton("all", "", distribution, eval(parseInt(jobId) + 1));
+}
+function queryJobListUserName(distribution, name) {
+       var encodingName = encodeURIComponent(name);
+       queryJobListByButton("user", encodingName, distribution, "LATEST");
+}
+
+function queryJobListUserGroup(distribution, group) {
+       queryJobListByButton("group", group, distribution, "LATEST");
+}
+
+function queryJobListProject(distribution, project) {
+       queryJobListByButton("project", project, distribution, "LATEST");
+}
+
+function queryJobListDate(distribution, date) {
+       queryJobListByButton("date", date, distribution, "LATEST");
+}
+
+function queryJobListByButton(condition, param, distribution, jobId) {
+       clearJobList();
+       clearRequestList();
+       var selectedStatus= $('#jobStatusSelect').find("input[type='radio']:checked").val();
+       var request = queryJobList("jobs/list", condition, param, distribution, selectedStatus, jobId);
+       if(request != undefined) {
+               request.done(function() {
+                       console.log("Start update");
+                       jobUpdateList(condition, param, distribution, selectedStatus);
+               });
+       }
+}
+
+function jobQueryDistribution() {
+       if( $("#jobSelectDistribution").children().length == 0 ) {
+               queryDistribution( function(xml) {
+                       // remove old select options
+                       $("#jobSelectDistribution").empty();
+                       $("#jobSelectDistribution").append("<option value='ALL'>ALL</option>");
+               
+                       $(xml).find("Data").find("DistributionName").each(function(){
+                               var name = $(this).text();
+               
+                               $("#jobSelectDistribution").append("<option value=\'"+name+"\'>"+name+"</option>");
+                       });
+               
+                       /* default distribution selection */
+                       $("#jobSelectDistribution option:eq(0)").attr("selected", "selected");
+                       $("#jobSelectDistribution").selectmenu('refresh');
+    
+                       selectJobAll();
+               });
+       } else {
+               jobsSearchSelected();
+       }
+}
+
+function queryJobList(requestUrl, condition, param, queryDistribution, selectedStatus, jobId) {
+       var url = "";
+       if(condition == "all") {
+               url = requestUrl+"/"+condition+"/"+queryDistribution+"/"+selectedStatus+"/"+jobId;
+       }
+       else {
+               url = requestUrl+"/"+condition+"/"+param+"/"+queryDistribution+"/"+selectedStatus+"/"+jobId;
+       }
+       console.log("url :"+url);
+       return queryJobsList(url, function(xml) {
+               var lastJobId = 0;
+               $(xml).find("JobList").find("Job").each(function(){
+                       var id = $(this).find("Id").text();
+                       var li = generateHtmlJobList($(this));
+
+                       lastJobId = id;
+                       $("#jobList").append(li).listview('refresh');
+
+                       $("#jobs-li-link-"+id).popupWindow({ 
+                               height:900, 
+                               width:800, 
+                               top:30, 
+                               left:50 
+                       });
+               });
+
+               console.log("last job id :"+lastJobId);
+               if(lastJobId > 0)
+               {
+                       var moreJobListUrl = 'queryJobList("'+requestUrl+'", "'+condition+'", "'+param+'", "'+queryDistribution+'", "'+selectedStatus+'", "'+lastJobId+'")';
+                       console.log(moreJobListUrl);
+                       $('#moreJobList').attr("onClick", moreJobListUrl);
+                       $('#moreJobList').removeClass('ui-disabled');
+               }
+               else
+               {
+                       $('#moreJobList').addClass('ui-disabled');
+               }
+               $('#moreJobList').button('refresh');
+
+       }, errorProcess); 
+}
+
+function jobUpdateList(condition, param, distribution, selectedStatus) {
+       var latest_job_id= $("#jobList li").first().attr("title");
+       if(latest_job_id == undefined) {
+               latest_job_id = 0;
+       }
+       var working_job_list = searchWorkingList();
+       item = {"Condition":condition, "Param":param, "Distribution":distribution, "Status":selectedStatus, "LatestId":latest_job_id, "WorkingJobId":working_job_list};
+
+       var update_ajax = updateList(item, function(xml) {
+               var firstLi= $("#jobList li").first();
+
+               // Add new job list
+               $(xml).find("JobList").find("Job").each(function(){
+                       var id = $(this).find("Id").text();
+                       var li = generateHtmlJobList($(this));
+
+                       $(li).insertBefore(firstLi);
+                       $("#jobList").listview('refresh');
+                       $("#jobs-li-link-"+id).popupWindow({ 
+                               height:900, 
+                               width:800, 
+                               top:30, 
+                               left:50 
+                       });
+                       console.log("ADD List :"+id);
+               });
+
+               // Update working job list
+               $(xml).find("WorkingJobList").find("Job").each(function(){
+                       var job_id = $(this).find("Id").text();
+                       var parent_job_id = $(this).find("ParentJobId").text();
+                       var job_status = $(this).find("Status").text();
+                       var start_time = $(this).find("StartTime").text();
+                       var end_time = $(this).find("EndTime").text();
+                       var font_color = "black";
+
+                       switch(job_status)
+                       {
+                               case "ERROR" :
+                               case "CANCELED" :
+                                       font_color = "red";
+                                       break;
+                               case "INITIALIZING" :
+                               case "JUST_CREATED" :
+                               case "PENDING" :
+                               case "WORKING" :
+                               case "REMOTE_WORKING" :
+                                       font_color = "blue";
+                                       break;
+                               case "WAITING" :
+                                       font_color = "green";
+                                       break;
+                               case "FINISHED" :
+                                       font_color = "black";
+                                       break;
+                               default:
+                                       console.error(job_status+" status is not define.");
+                                       font_color = "black";
+                                       break;
+                       }
+                       
+                       // in case, exist job list element or not exist
+                       if($("#jobs-li-"+job_id).length != 0) {
+                               var html_status = '<strong><font color="'+font_color+'">'+job_status+'</strong>';
+                               var html_time = 'TIME: <strong>' +start_time+ ' ~ '+end_time+ '</strong>';
+                               $("#jobs-li-status-"+job_id).html(html_status);
+                               $("#jobs-li-time-"+job_id).html(html_time);
+                               console.log("UPDATE List :"+job_id);
+                       }
+                       else {
+                               var next_parent_job_li = $("#jobs-li-"+parent_job_id).nextAll(".jobs-li-header").first();
+                               console.log(parent_job_id);
+                               console.log($("#jobs-li-"+parent_job_id));
+                               console.log(next_parent_job_li);
+                               console.log(next_parent_job_li.text());
+
+                               var li = generateHtmlJobList($(this));
+
+                               $(li).insertBefore(next_parent_job_li);
+                               $("#jobList").listview('refresh');
+                               $("#jobs-li-link-"+job_id).popupWindow({ 
+                                       height:900, 
+                                       width:800, 
+                                       top:30, 
+                                       left:50 
+                               });
+                               console.log("ADD child list :"+job_id);
+                       }
+               });
+       });
+
+       var idx = addRequestList(update_ajax);
+       update_ajax.done(function() {
+               console.log("update complete. retry in 2 sec.");
+               setTimeout(function(){
+                       if(isPolling(idx) && $.mobile.activePage.attr('id') == "jobs" && idx < 900) {
+                               console.log("Update request.");
+                               request_list[idx].polling = false;
+                               jobUpdateList(condition, param, distribution, selectedStatus);
+                       }
+                       else {
+                               console.log("Stop update.");
+                       }
+               }, 2000);
+       });
+}
+
+function clearSuggestJobSearchList() {
+       $("#jobSearchList").empty();
+}
+
+function jobsQueryGroupList() {
+       suggestion_list = [];
+
+       queryAllGroup( function(xml) {
+               var idx = 0;
+
+               $(xml).find("Data").find("GroupName").each(function(){
+                       suggestion_list[idx]= $(this).text();
+                       idx++;
+               });
+       }, errorProcess);
+}
+
+function suggestJobSearchList(inputText) {
+       var sugList = $("#jobSearchList");
+
+       if(inputText.length < 1) {
+               sugList.html("");
+               sugList.listview("refresh");
+       } else {
+               var str = "";
+               var suggestion = "";
+               for(var i=0, len=suggestion_list.length; i<len; i++) {
+                       suggestion = suggestion_list[i];
+
+                       if(suggestion.search(inputText) >= 0)
+                       {
+                               str += "<li data-mini='true'><a href='#' onClick='jobSuggestListClick(\""+suggestion+"\")'>"+suggestion+"</a></li>";
+                       }
+               }
+               sugList.html(str);
+               sugList.listview("refresh");
+       }
+}
+
+function jobSuggestListClick(suggestText) {
+       $("#jobSearchInputText").val(suggestText);
+       $("#jobSearchList").empty();
+
+       var startIndex = suggestText.search(/\[/);
+       var endIndex = suggestText.search('\]');
+
+       if(startIndex > 0 && endIndex >0) {
+               project = suggestText.substr(0, startIndex);
+               distribution = suggestText.substr(startIndex+1, endIndex-startIndex-1);
+               queryJobListProject(distribution, project);
+       }
+       else {
+               searchJob(suggestText);
+       }
+}
+
+function jobsQueryProjectsList() {
+       var distribution = $("#jobSelectDistribution option:selected").val(); 
+       suggestion_list = [];
+
+       if(distribution == "ALL") {
+               queryAllProject(function(xml) {
+                       var idx = 0;
+       
+                       $(xml).find("Data").find("Project").each(function(){
+                               var projectName = $(this).find("Name").text();
+                               var distName = $(this).find("DistName").text();
+                               suggestion_list[idx]= projectName+"["+distName+"]"
+                               idx++;
+                       });
+               });
+       }
+       else {
+               queryProjectList(distribution, function(xml) {
+                       var idx = 0;
+       
+                       $(xml).find("Data").find("Project").each(function(){
+                               suggestion_list[idx]= $(this).find("ProjectName").text();
+                               idx++;
+                       });
+               });
+       }
+}
+
+function jobsClear() {
+       $("#jobSelectDistribution").empty();
+       clearJobList();
+}
+
+function generateHtmlJobList(xml) {
+       var id = xml.find("Id").text();
+       var distribution = xml.find("Distribution").text();
+       var projectName = xml.find("ProjectName").text();
+       var jobType = xml.find("JobType").text();
+       var jobAttribute = xml.find("JobAttribute").text();
+       var os = xml.find("Os").text();
+       var jobStatus = xml.find("Status").text();
+       var userName = xml.find("UserName").text();
+       var startTime = xml.find("StartTime").text();
+       var endTime = xml.find("EndTime").text();
+       var li = "";
+       var font_color = "black";
+
+       switch(jobStatus)
+       {
+               case "ERROR" :
+               case "CANCELED" :
+                       font_color = "red";
+                       break;
+               case "INITIALIZING" :
+               case "JUST_CREATED" :
+               case "PENDING" :
+               case "WORKING" :
+               case "REMOTE_WORKING" :
+                       font_color = "blue";
+                       break;
+               case "WAITING" :
+                       font_color = "green";
+                       break;
+               case "FINISHED" :
+                       font_color = "black";
+                       break;
+               default:
+                       console.error(job_status+" status is not define.");
+                       font_color = "black";
+                       break;
+       }
+
+       if(jobAttribute == "SINGLE")
+       {
+               li = '<li class="jobs-li-header" data-role="list-divider" title="'+id+'">'
+                       + '<span>'+id+ ' ' +projectName+ '</span><span style="float: right">'+distribution+'</span></li>'
+                       + '<li id="jobs-li-'+id+'" class="jobs-list-data" title="'+id+'">'
+                       + '<a href=log.html?jobid='+id+' id="jobs-li-link-'+id+'" class="logWindow" data-ajax="false">'
+                       + '<h3>' +projectName+ '</h3>'
+                       + '<p>ID : <strong>' +id+ '</strong></p>'
+                       + '<p>TYPE : <strong>' +jobType+ '</strong></p>'
+                       + '<p>OS : <strong>' + os + '</strong></p>'
+                       + '<p>USER : <strong>' +userName+ '</strong></p>'
+                       + '<p id="jobs-li-time-'+id+'">TIME: <strong>' +startTime+ ' ~ '+endTime+ '</strong></p>';
+                        
+                       li = li + '<p id="jobs-li-status-'+id+'" class="ui-li-aside jobs-li-status"><strong><font color="'+font_color+'">'+jobStatus+'</strong></p>';
+                       li = li + '<div hidden="hidden" class="jobs-li-hidden ui-screen-hidden">'
+                               + '<p class="jobs-li-hidden-id">'+id+'</p>'
+                               + '<p class="jobs-li-hidden-attr">'+jobAttribute+'</p>'
+                               + '</div>';
+                       li = li + '</a></li>';
+       }
+       else if(jobAttribute == "MULTI")
+       {
+               li = '<li class="jobs-li-header" data-role="list-divider" title="'+id+'">'
+                       + '<span>'+id+ ' ' +jobAttribute+ '</span><span style="float: right">'+distribution+'</span></li>'
+                       + '<li id="jobs-li-'+id+'" class="jobs-list-data" title="'+id+'">'
+                       + '<a href=log.html?jobid='+id+' id="jobs-li-link-'+id+'" class="logWindow" data-ajax="false">'
+                       + '<p>USER : <strong>' +userName+ '</strong></p>'
+                       + '<p id="jobs-li-time-'+id+'">TIME: <strong>' +startTime+ ' ~ '+endTime+ '</strong></p>';
+                       + '<p id="jobs-li-attr-'+id+'" hidden="hidden">'+jobAttribute+'</p>';
+                       
+                       li = li + '<p id="jobs-li-status-'+id+'" class="ui-li-aside jobs-li-status" title="'+id+'"><strong><font color="'+font_color+'">'+jobStatus+'</strong></p>';
+                       li = li + '<div hidden="hidden" class="jobs-li-hidden ui-screen-hidden">'
+                               + '<p class="jobs-li-hidden-id">'+id+'</p>'
+                               + '<p class="jobs-li-hidden-attr">'+jobAttribute+'</p>'
+                               + '</div>';
+                       li = li + '</a></li>';
+       }
+       else if(jobAttribute == "CHILD")
+       {
+               li = '<li id="jobs-li-'+id+'" class="jobs-list-data" title="'+id+'">'
+                       + '<a href=log.html?jobid='+id+' id="jobs-li-link-'+id+'" class="logWindow" data-ajax="false">'
+                       + '<h3>' +projectName+ '</h3>'
+                       + '<p>ID : <strong>' +id+ '</strong></p>'
+                       + '<p>TYPE : <strong>' +jobType+ '</strong></p>'
+                       + '<p>OS : <strong>' +os+ '</strong></p>'
+                       + '<p id="jobs-li-time-'+id+'">TIME: <strong>' +startTime+ ' ~ '+endTime+ '</strong></p>';
+                       + '<p id="jobs-li-attr-'+id+'" hidden="hidden">'+jobAttribute+'</p>';
+                       
+                       li = li + '<p id="jobs-li-status-'+id+'" class="ui-li-aside jobs-list-status" title="'+id+'"><strong><font color="'+font_color+'">'+jobStatus+'</strong></p>';
+                       li = li + '<div hidden="hidden" class="jobs-li-hidden ui-screen-hidden">'
+                               + '<p class="jobs-li-hidden-id">'+id+'</p>'
+                               + '<p class="jobs-li-hidden-attr">'+jobAttribute+'</p>'
+                               + '</div>';
+                       li = li + '</a></li>';
+       }
+
+       return li;
+}
+
+function searchWorkingList() {
+       working_job_array = new Array();
+       $("#jobList .jobs-list-data").each(function(index) {
+               var job_attr = $(this).find(".jobs-li-hidden-attr").text();
+               var job_id = $(this).find(".jobs-li-hidden-id").text();
+               var job_status= $(this).find(".jobs-li-status").text();
+               switch(job_status)
+               {
+                       case "INITIALIZING" :
+                       case "JUST_CREATED" :
+                       case "PENDING" :
+                       case "WORKING" :
+                       case "REMOTE_WORKING" :
+                       case "WAITING" :
+                               if(job_attr != "CHILD") {
+                                       working_job_array.push(job_id);
+                               }
+                               break;
+                       default:
+                               break;
+               }
+       });
+       return working_job_array;
+}
+
+/* For background update AJAX */
+function classAjax() {
+       var polling = false;
+       var ajaxObj = undefined;
+}
+
+function addRequestList(ajaxObj) {
+       var class_ajax = new classAjax();
+       class_ajax.polling = true;
+       class_ajax.ajaxObj = ajaxObj;
+       
+       return request_list.push(class_ajax) - 1;
+}
+
+function clearRequestList() {
+       while(request_list.length > 0) {
+               var last_request = request_list[request_list.length - 1];
+               if(last_request.polling == true && last_request.ajaxObj != undefined) {
+                       last_request.ajaxObj.abort();
+               }
+               request_list.pop();
+       }
+       console.log("Clear all update.");
+}
+
+function isPolling(idx) {
+       if(request_list[idx] != undefined) {
+               return request_list[idx].polling;
+       }
+       else {
+               return false;
+       }
+}
+
diff --git a/dibs-web/public/javascripts/log.js b/dibs-web/public/javascripts/log.js
new file mode 100644 (file)
index 0000000..607b68c
--- /dev/null
@@ -0,0 +1,184 @@
+/* 
+ log.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+var request;
+var stop = 1;
+
+var baseUrl;
+var job_id;
+var last_line = 0;
+
+var init = function () {
+       console.log("init() called");
+       var myUrl = location.href;
+       var varCut = myUrl.indexOf("?");
+       var varCheck = myUrl.substring(varCut+1);
+       eval(varCheck);
+
+       job_id = jobid;
+       $('#job-info-id').text(job_id);
+       console.log(job_id);
+
+       var baseCut = myUrl.indexOf("log.html");
+
+       baseUrl = myUrl.substring(0, baseCut);
+       console.log("base url:"+baseUrl);
+
+       queryLog();
+};
+
+$(document).ready(init);
+
+function queryLog()
+{
+       var next_line = Number(last_line) + 1;
+       queryJobsLog(job_id, next_line, function(xml) {
+               /* pre-process for header */
+               job_id = $(xml).find("Data").find("JobId").text();
+               var distribution = $(xml).find("Data").find("Distribution").text();
+               var project = $(xml).find("Data").find("Project").text();
+               var builder = $(xml).find("Data").find("Builder").text();
+               var job_status = $(xml).find("Data").find("Status").text();
+               var time = $(xml).find("Data").find("Time").text();
+               var conti = Number($(xml).find("Data").find("Continue").text());
+               var working_status = 0;
+       
+               $('#job-info-distribution').html(distribution);
+               $('#job-info-project').html(project);
+               $('#job-info-builder').html(builder);
+               $('#job-info-status').html(job_status);
+               switch(job_status)
+               {
+                       case "ERROR" :
+                       case "CANCELED" :
+                               $('#job-info-status').css("color","red");
+                               $('#job-info-cancel input').attr("disabled", true);
+                               working_status = 0;
+                               break;
+                       case "INITIALIZING" :
+                       case "JUST_CREATED" :
+                       case "PENDING" :
+                       case "WORKING" :
+                       case "REMOTE_WORKING" :
+                               $('#job-info-status').css("color","blue");
+                               working_status = 1;
+                               break;
+                       case "WAITING" :
+                               $('#job-info-status').css("color","green");
+                               working_status = 1;
+                               break;
+                       case "FINISHED" :
+                               $('#job-info-status').css("color","black");
+                               $('#job-info-cancel input').attr("disabled", true);
+                               working_status = 0;
+                               break;
+                       default:
+                               console.error(job_status+" status is not define.");
+                               $('#job-info-cancel input').attr("disabled", true);
+                               working_status = 0;
+                               break;
+               }
+
+               /* Insert data */
+               $(xml).find("Data").find("LogData").each(function() {
+                       var insertTable = document.getElementById("logTable");
+                       var insertRow = document.createElement("tr");
+                       var insertCel1 = document.createElement("td");
+                       var insertCel2 = document.createElement("td");
+       
+                       var line_number = $(this).attr("Line");
+                       var line_data =  $(this).text();
+       
+                       insertCel1.width = '30';
+                       insertCel1.style.textAlign = 'right';
+                       insertCel1.style.cellpacing = '5';
+                       insertCel1.innerHTML = line_number;
+                       last_line = line_number;
+       
+                       insertCel2.style.textAlign = 'left';
+                       insertCel2.innerHTML = line_data;
+       
+                       insertRow.appendChild(insertCel1);
+                       insertRow.appendChild(insertCel2);
+       
+                       insertTable.appendChild(insertRow);
+       
+               });
+
+               if(working_status == 1){
+                       console.log("scroll");
+                       scrollToBottom();
+               }
+       
+               autoQueryLog(conti, working_status);
+       });
+}
+
+function autoQueryLog(conti, working_status) {
+       if(conti && stop) {
+               queryLog();
+       }
+
+       if(working_status == 1 && stop) {
+               console.log("status is working. try request");
+               setTimeout(function(){queryLog()}, 3000);
+       }
+}
+
+function stopLog() {
+       stop = 0;
+}
+
+function moreLog() {
+       stop = 1;
+       queryLog();
+}
+
+function cancelJob() {
+       cancelJobsJobid(job_id, function(xml) {
+               alert("Reqeusted cancel job : "+job_id);
+       });
+}
+
+function getYScroll()
+{
+       var yScroll;  
+       if (window.innerHeight && window.scrollMaxY) {                  
+               yScroll = window.innerHeight + window.scrollMaxY;
+       } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
+               yScroll = document.body.scrollHeight;
+       } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
+               yScroll = document.body.offsetHeight;
+       }
+       return yScroll;
+}
+
+function scrollToBottom() {
+       window.scrollTo(0,getYScroll());
+}
+
diff --git a/dibs-web/public/javascripts/main.js b/dibs-web/public/javascripts/main.js
new file mode 100644 (file)
index 0000000..bb60f7f
--- /dev/null
@@ -0,0 +1,337 @@
+/* 
+ main.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+//Initialize function
+var baseUrl = "";
+
+var init = function () {
+       console.log("init() called");
+       var myUrl = location.href;
+       var urlCut = myUrl.indexOf("index.html");
+       var     sharpCut = myUrl.indexOf("#");
+
+       if(urlCut > 0) {
+               baseUrl = myUrl.substring(0, urlCut);
+       }
+       else if(sharpCut > 0) {
+               baseUrl = myUrl.substring(0, sharpCut);
+       }
+       else {
+               baseUrl = window.location.href;
+       }
+       console.log("base url:"+baseUrl);
+};
+$(document).ready(init);
+
+$.ajaxSetup({
+       beforeSend: function(xhr) {
+       xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
+  }
+}); 
+
+
+$( document ).bind( "pageshow", function( event, data ){
+});
+
+$( document ).bind( "pagechange", function( event, data ){
+       var id = $.mobile.activePage.attr('id');
+
+       switch(id){
+               case "index":
+                       generateNavigationBar(id);
+                       break;
+               case "signup":
+                       clearFormData('signupForm');
+                       break;
+               case "login":
+                       clearFormData('loginForm');
+                       break;
+               case "projects":
+                       generateNavigationBar(id);
+                       projectsInit(id);
+                       break;
+               case "build":
+                       generateNavigationBar(id);
+                       buildInit(id);
+                       break;
+               case "jobs":
+                       generateNavigationBar(id);
+                       jobsInit();
+                       break;
+               case "log":
+                       logInit();
+                       break;
+               case "adminUser":
+                       generateNavigationBar(id);
+                       adminUserInit();
+                       break;
+               case "adminGroup":
+                       generateNavigationBar(id);
+                       adminGroupInit();
+                       break;
+               case "adminServer":
+                       generateNavigationBar(id);
+                       adminServerInit();
+                       break;
+               case "adminProject":
+                       generateNavigationBar(id);
+                       adminProjectInit();
+                       break;
+               case "adminDistribution":
+                       generateNavigationBar(id);
+                       adminDistributionInit();
+                       break;
+               case "modifyDistribution":
+                       adminDistributionModifyPopupInit();
+                       break;
+               case "adminUserModifyPopup":
+                       adminUserModifyPopupInit();
+                       break;
+               case "modifyBinaryProject":
+                       adminProjectModifyBinaryProjectInit();
+                       break;
+               case "modifyGitProject":
+                       adminProjectModifyGitProjectInit();
+                       break;
+               case "adminGroupAddPopup":
+                       adminGroupAddInit();
+                       break;
+               case "adminGroupModifyPopup":
+                       adminGroupModifyInit();
+                       break;
+               case "adminServerModifyRemoteBuildServer":
+                       adminServerModifyRemoteBuildServerInit();
+                       break;
+               case "addGitProject":
+                       adminProjectAddGitInit();
+                       break;
+               case "addBinaryProject":
+                       adminProjectAddBinaryInit();
+                       break;
+               case "adminServerAddSupportedOs":
+                       adminServerAddSupportedOsInit();
+                       break;
+               case "adminServerRemoveOSCategory":
+                       adminServerRemoveOSCategoryInit();
+                       break;
+               case "signup":
+                       //queryGroupListForSignup();
+                       break;
+               default:
+                       break;
+       }
+       
+       // Call check session info
+       checkSessionInfo();
+});
+
+$( document ).bind( "mobileinit", function() {
+       $.support.cors                           = true;
+       $.support.cors                           = true;
+       $.mobile.pushStateEnabled         = false;
+});
+
+function clearFormData(elementId){
+       $("#"+elementId).find(':input').each(function() {
+               switch(this.type) {
+                       case 'text':
+                       case 'password':
+                       case 'select-multiple':
+                       case 'select-one':
+                       case 'textarea':
+                               $(this).val('');
+                               break;
+                       case 'checkbox':
+                       case 'radio':
+                               $(this).checked = false;
+                               break;
+               }
+       });
+}
+
+function generateNavigationBar(id) {
+       if(sessionStorage.sessionInfoEmail) 
+       {
+               var admin = sessionStorage.sessionInfoAdmin;
+               if(admin == "TRUE")
+               {
+                       generateNavigationBarAdmin(id);
+               }
+               else
+               {
+                       generateNavigationBarUser(id);
+               }
+       } else {
+               $("#"+id+"-navigationBar").empty();
+       }
+}
+
+function generateNavigationBarUser(id) {
+       var naviHtml = ""
+       naviHtml = '<li data-role="list-divider">BUILD</li>';
+       switch(id){
+               case "projects":
+                       naviHtml += '<li data-theme="b" ><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       break;
+               case "build":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li data-theme="b"><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       break;
+               case "jobs":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li data-theme="b"><a href="#jobs">Jobs</a></li>';
+                       break;
+               default:
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       break;
+       }
+
+       $("#"+id+"-navigationBar").empty();
+       $("#"+id+"-navigationBar").append(naviHtml).listview("refresh");
+}
+
+function generateNavigationBarAdmin(id) {
+       var naviHtml = ""
+       naviHtml = '<li data-role="list-divider">BUILD</li>';
+       switch(id){
+               case "projects":
+                       naviHtml += '<li data-theme="b" ><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "build":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li data-theme="b" ><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "jobs":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li data-theme="b" ><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "adminUser":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li data-theme="b" ><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "adminGroup":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li data-theme="b" ><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "adminServer":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li data-theme="b" ><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "adminDistribution":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li data-theme="b" ><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+               case "adminProject":
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li data-theme="b" ><a href="#adminProject">Project</a></li>';
+                       break;
+               default:
+                       naviHtml += '<li><a href="#projects">Projects</a></li>';
+                       naviHtml += '<li><a href="#build">Build</a></li>';
+                       naviHtml += '<li><a href="#jobs">Jobs</a></li>';
+                       naviHtml += '<li data-role="list-divider">ADMIN</li>';
+                       naviHtml += '<li><a href="#adminUser">User</a></li>';
+                       naviHtml += '<li><a href="#adminGroup">Group</a></li>';
+                       naviHtml += '<li><a href="#adminServer">Server</a></li>';
+                       naviHtml += '<li><a href="#adminDistribution">Distribution</a></li>';
+                       naviHtml += '<li><a href="#adminProject">Project</a></li>';
+                       break;
+       }
+
+       $("#"+id+"-navigationBar").empty();
+       $("#"+id+"-navigationBar").append(naviHtml).listview("refresh");
+}
+
+function dibsWebClear(){
+       projectsClear();
+       buildClear();
+       jobsClear();
+}
diff --git a/dibs-web/public/javascripts/popup-window.js b/dibs-web/public/javascripts/popup-window.js
new file mode 100644 (file)
index 0000000..fd5d493
--- /dev/null
@@ -0,0 +1,90 @@
+/* 
+ popup-window.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+(function($){
+       $.fn.popupWindow = function(instanceSettings){
+
+               return this.each(function(){
+
+               $(this).click(function(){
+
+               $.fn.popupWindow.defaultSettings = {
+                       centerBrowser:0, // center window over browser window? {1 (YES) or 0 (NO)}. overrides top and left
+                       centerScreen:0, // center window over entire screen? {1 (YES) or 0 (NO)}. overrides top and left
+                       height:500, // sets the height in pixels of the window.
+                       left:0, // left position when the window appears.
+                       location:1, // determines whether the address bar is displayed {1 (YES) or 0 (NO)}.
+                       menubar:0, // determines whether the menu bar is displayed {1 (YES) or 0 (NO)}.
+                       resizable:0, // whether the window can be resized {1 (YES) or 0 (NO)}. Can also be overloaded using resizable.
+                       scrollbars:1, // determines whether scrollbars appear on the window {1 (YES) or 0 (NO)}.
+                       status:0, // whether a status line appears at the bottom of the window {1 (YES) or 0 (NO)}.
+                       width:500, // sets the width in pixels of the window.
+                       windowName:null, // name of window set from the name attribute of the element that invokes the click
+                       windowURL:null, // url used for the popup
+                       top:0, // top position when the window appears.
+                       toolbar:0 // determines whether a toolbar (includes the forward and back buttons) is displayed {1 (YES) or 0 (NO)}.
+               };
+               
+               settings = $.extend({}, $.fn.popupWindow.defaultSettings, instanceSettings || {});
+               
+               var windowFeatures =    'height=' + settings.height +
+                                                               ',width=' + settings.width +
+                                                               ',toolbar=' + settings.toolbar +
+                                                               ',scrollbars=' + settings.scrollbars +
+                                                               ',status=' + settings.status + 
+                                                               ',resizable=' + settings.resizable +
+                                                               ',location=' + settings.location +
+                                                               ',menuBar=' + settings.menubar;
+
+                               settings.windowName = this.name || settings.windowName;
+                               settings.windowURL = this.href || settings.windowURL;
+                               var centeredY,centeredX;
+                       
+                               if(settings.centerBrowser){
+                                               
+                                       if ($.browser.msie) {//hacked together for IE browsers
+                                               centeredY = (window.screenTop - 120) + ((((document.documentElement.clientHeight + 120)/2) - (settings.height/2)));
+                                               centeredX = window.screenLeft + ((((document.body.offsetWidth + 20)/2) - (settings.width/2)));
+                                       }else{
+                                               centeredY = window.screenY + (((window.outerHeight/2) - (settings.height/2)));
+                                               centeredX = window.screenX + (((window.outerWidth/2) - (settings.width/2)));
+                                       }
+                                       window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + centeredX +',top=' + centeredY).focus();
+                               }else if(settings.centerScreen){
+                                       centeredY = (screen.height - settings.height)/2;
+                                       centeredX = (screen.width - settings.width)/2;
+                                       window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + centeredX +',top=' + centeredY).focus();
+                               }else{
+                                       window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + settings.left +',top=' + settings.top).focus();
+                               }
+                               return false;
+                       });
+
+               });
+       };
+})(jQuery);
diff --git a/dibs-web/public/javascripts/post-process.js b/dibs-web/public/javascripts/post-process.js
new file mode 100644 (file)
index 0000000..0c0aaaa
--- /dev/null
@@ -0,0 +1,35 @@
+/* 
+ post-process.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+$('.uploadWindow').popupWindow({ 
+       height:200, 
+       width:400, 
+       top:50, 
+       left:50 
+});
+
diff --git a/dibs-web/public/javascripts/projects.js b/dibs-web/public/javascripts/projects.js
new file mode 100644 (file)
index 0000000..2288665
--- /dev/null
@@ -0,0 +1,178 @@
+/* 
+ projects.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+function projectsInit() {
+       if( $("#projects-select-distribution").children().length == 0 ) {
+               queryDistribution( function(xml) {
+                       // remove old select options
+                       $("#projects-select-distribution").empty();
+               
+                       $(xml).find("Data").find("DistributionName").each(function(){
+                               var name = $(this).text();
+               
+                               $("#projects-select-distribution").append("<option value=\'"+name+"\'>"+name+"</option>");
+                       });
+               
+                       /* default distribution selection */
+                       $("#projects-select-distribution option:eq(0)").attr("selected", "selected");
+                       $("#projects-select-distribution").selectmenu('refresh');
+               
+                       projectsQueryProjectListType("MY"); 
+                       $('#projectsSearchSelect input[type="radio"]').attr("checked",false).checkboxradio("refresh");
+                       $('#projectsSearchSelect input[type="radio"]:first').attr("checked",true).checkboxradio("refresh");
+               });
+       } else {
+               projectsQueryProjectListType("MY"); 
+               $('#projectsSearchSelect input[type="radio"]').attr("checked",false).checkboxradio("refresh");
+               $('#projectsSearchSelect input[type="radio"]:first').attr("checked",true).checkboxradio("refresh");
+       }
+}
+
+function projectsQueryProjectListType(queryType) {
+       var distName = $("#projects-select-distribution option:selected").val();
+
+       queryProjectsInfoInDistribution( distName, function(xml) {
+               var projectList = document.getElementById("projects-project-list");
+
+               /* remove all list */
+               while(projectList.hasChildNodes())
+               {
+                       projectList.removeChild(projectList.firstChild);
+               }
+
+               $(xml).find("Data").find("ProjectList").find("Project").each(function(){
+                       switch(queryType) {
+                               case "ALL":
+                                       projectsAppendProjectList($(this), projectList);
+                                       break;
+                               case "MY":
+                                       var groupAccess = $(this).find("GroupAccess").text();
+                                       if(groupAccess == "TRUE") {
+                                               projectsAppendProjectList($(this), projectList);
+                                       }
+                                       break;
+                               case "GIT":
+                                       var type = $(this).find("Type").text();
+                                       if(type == "GIT") {
+                                               projectsAppendProjectList($(this), projectList);
+                                       }
+                                       break;
+                               case "BINARY":
+                                       var type = $(this).find("Type").text();
+                                       if(type == "BINARY") {
+                                               projectsAppendProjectList($(this), projectList);
+                                       }
+                                       break;
+                               default:
+                                       ;
+                       }
+               });
+
+               $('.projects-project-list-collapsible').collapsible();
+               $('.projects-project-list-listview').listview();
+               
+       });
+}
+
+function projectsAppendProjectList( project, projectList ) {
+       var name = project.find("Name").text();
+       var type = project.find("Type").text();
+       var groupAccess = project.find("GroupAccess").text();
+       var maintainer = project.find("Maintainer").text();
+
+       var div = document.createElement('div');
+       div.setAttribute('data-role', 'collapsible');
+       div.setAttribute('data-inset', 'false');
+       div.setAttribute('data-mini', 'true');
+       div.setAttribute('class', 'projects-project-list-collapsible');
+       if(groupAccess == "TRUE") {
+               div.setAttribute('data-theme', "b");
+       }
+       else {
+               div.setAttribute('data-theme', "d");
+       }
+       projectList.appendChild(div);
+
+       var h2 = document.createElement('h2');
+       h2.innerHTML = '<span class="alignleft">'+name+'</span><span class="alignright">'+type+'</span>';
+       div.appendChild(h2);
+
+       var infoLine = document.createElement('p');
+       infoLine.setAttribute('style', 'font-size: 12px');
+       infoLine.innerHTML = "Maintainer : "+maintainer+"<br><br>";
+       div.appendChild(infoLine);
+
+       var ul = document.createElement('ul');
+       ul.setAttribute('data-role', "listview");
+       ul.setAttribute('class', "projects-project-list-listview");
+       ul.setAttribute('data-filter-theme', "c");
+       ul.setAttribute('data-divider-theme', "c");
+       div.appendChild(ul);
+
+       project.find("ProjectOs").each(function(){
+               var osName = $(this).find("OsName").text();
+
+               var li = document.createElement('li');
+               li.setAttribute('style', 'font-size: 12px');
+               li.setAttribute('data-role', "list-divider")
+               li.innerHTML = "<strong>"+osName+"</strong>";
+               ul.appendChild(li);
+
+               $(this).find("Package").each(function(){
+                       var packageName = $(this).find("PackageName").text();
+                       var packageVersion = $(this).find("PackageVersion").text(); 
+                       var startTime = $(this).find("StartTime").text(); 
+                       var endTime= $(this).find("EndTime").text(); 
+                       var userName = $(this).find("UserName").text(); 
+                       var userEmail = $(this).find("UserEmail").text(); 
+            
+                       if(packageName != "")
+                       {
+                               var liInfo = document.createElement('li');
+                               liInfo.setAttribute('style', 'font-size: 12px');
+                               var info = "<h3>"+packageName+" "+packageVersion+"</h3>";
+                               info += "<p>Lastest build time : <strong>"+startTime+" ~ "+endTime+"</strong></p>";
+                               info += "<p>Lastest build user : <strong>"+userName+" ["+userEmail+"]</strong></p>";
+                               liInfo.innerHTML = info;
+                               ul.appendChild(liInfo);
+                       }
+               });
+       });
+}
+
+function projectsClear() {
+       $("#projects-select-distribution").empty();
+
+       var projectList = document.getElementById("projects-project-list");
+       /* remove all list */
+       while(projectList.hasChildNodes())
+       {
+               projectList.removeChild(projectList.firstChild);
+       }
+}
+
diff --git a/dibs-web/public/javascripts/session.js b/dibs-web/public/javascripts/session.js
new file mode 100644 (file)
index 0000000..12582dc
--- /dev/null
@@ -0,0 +1,146 @@
+/* 
+ session.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+$(function() {
+       $('#login-password').keypress(function() {
+               if(event.keyCode == '13') {
+                       sessionLogin();
+               }
+       });
+});
+
+function setSessionInfo(xml){
+       var email = $(xml).find("Header").find("UserInfo").find("Email").text();
+       var name = $(xml).find("Header").find("UserInfo").find("Name").text();
+       var admin = $(xml).find("Header").find("UserInfo").find("Admin").text();
+       var group;
+       var idx = 0;
+       $(xml).find("Header").find("UserInfo").find("GroupList").find("Group").each(function() {
+               if(idx == 0) {
+                       group = $(this).find("GroupName").text();
+               }
+       });
+
+       sessionStorage.sessionInfoEmail = email;
+       sessionStorage.sessionInfoName = name;
+       sessionStorage.sessionInfoGroup = group;
+       sessionStorage.sessionInfoAdmin = admin;
+       
+       checkSessionInfo();
+}
+
+function checkSessionInfo(){
+       var email = sessionStorage.sessionInfoEmail;
+       var name = sessionStorage.sessionInfoName;
+
+       if(email)
+       {
+               sessionHtml = '<div data-role="controlgroup" style="text-align: left; font-size: 12px" data-type="horizontal" class="ui-btn-right ui-btn-corner-all">';
+               sessionHtml += '<p data-direction="reverse" ><a href="#userModifyPopup" onClick="userQueryUserInfo()" data-rel="dialog">'+name+'</a> | ';
+               sessionHtml += '<a href=# onClick="logout()" data-direction="reverse">Log out</a></p></div>';
+       }
+       else
+       {
+               sessionHtml = '<div data-role="controlgroup" data-type="horizontal" class="ui-btn-right ui-btn-corner-all">';
+               sessionHtml += '<a href=#signup data-direction="reverse" data-role="button" data-rel="dialog">Sign up</a>';
+               sessionHtml += '<a href=#login data-direction="reverse" data-role="button" data-rel="dialog">Log in</a> </div>';
+       }
+       $(".sessionInfo").html(sessionHtml).trigger("create");
+}
+
+function clearSessionInfo(){
+       sessionStorage.sessionInfoEmail = "";
+       sessionStorage.sessionInfoName = "";
+       sessionStorage.sessionInfoGroup = "";
+       sessionStorage.sessionInfoAdmin = "";
+}
+
+function expireSession(){
+       clearSessionInfo();
+       $.mobile.changePage("index.html"); 
+       generateNavigationBar("index");
+}
+
+function sessionLogin() {
+       var infoList = [];
+       var infoItem;
+       var email = $('#login-email').val();
+       var password = $('#login-password').val();
+
+       if(email == ""){
+               alert("Email is invalid");
+               return false;
+       }
+
+       if(password == ""){
+               alert("Password is invalid");
+               return false;
+       }
+
+       changeInfoItem = {"Type":"ModifyUser", "Email":email, "Password":password };
+       infoList.push(changeInfoItem);
+
+       login(infoList, function (json) {
+               var result = json.Result;
+               var message = json.UserInfo.Message;
+               var email = json.UserInfo.Eamil;
+               var name = json.UserInfo.Name;
+               var group = json.UserInfo.GroupName;
+               var admin = json.UserInfo.Admin;
+
+               if(result == "SUCCESS")
+               {
+                       sessionStorage.sessionInfoEmail = email;
+                       sessionStorage.sessionInfoName = name;
+                       sessionStorage.sessionInfoGroup = group;
+                       sessionStorage.sessionInfoAdmin = admin;
+                       $.mobile.changePage("#index"); 
+               } 
+               else
+               {
+                       alert(message);
+                       }
+       });
+} 
+
+function signupQueryGroupList() {
+       queryAllGroup( function(xml) {
+               $("#applyGroupRadio").children().remove();
+
+               var newHtml ='<fieldset data-role="controlgroup" data-mini="true"><legend>Apply for group :</legend>';
+               $(xml).find("Data").find("GroupName").each(function(){
+                       var name = $(this).text();
+                       newHtml += '<input type="radio" name="group" id="group-'+name+'" value="'+name+'" />';
+                       newHtml += '<label for="group-'+name+'">'+name+'</label>';
+               });
+               console.log(newHtml);
+               $("#applyGroupRadio").append(newHtml).trigger('create');
+               $("#applyGroupRadio div[role='heading']").attr("style","text-align: left; font-size: 12px");
+       }, errorProcess);
+}
+
diff --git a/dibs-web/public/javascripts/user.js b/dibs-web/public/javascripts/user.js
new file mode 100644 (file)
index 0000000..70d8689
--- /dev/null
@@ -0,0 +1,136 @@
+/* 
+ user.js
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+*/
+
+$(function() {
+       $('#user-password-confirmation').keypress(function() {
+               if(event.keyCode == '13') {
+                       userSignUp();
+               }
+       });
+});
+
+function userSignUp() {
+       var infoList = [];
+       var infoItem;
+       var email = $('#user-email').val();
+       var name = $('#user-name').val();
+       var password = $('#user-password').val();
+       var password_confirm = $('#user-password-confirmation').val();
+       var emailCheckReg = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
+
+       if(email == "" || !emailCheckReg.test(email)){
+               alert("Email is invalid");
+               return false;
+       }
+       if(name == ""){
+               alert("Name is invalid");
+               return false;
+       }
+
+       if(password == ""){
+               alert("Password is invalid");
+               return false;
+       }
+
+       if(password != password_confirm){
+               alert("Password is different");
+               return false;
+       }
+
+       changeInfoItem = {"Type":"ModifyUser", "Email":email, "Name":name, "Password":password, "PasswordConfirm":password_confirm};
+       infoList.push(changeInfoItem);
+
+       signUp(infoList, function (json) {
+               alert("Success sign up");
+
+               var result = json.Result;
+               var message = json.UserInfo.Message;
+               var email = json.UserInfo.Eamil;
+               var name = json.UserInfo.Name;
+               var group = json.UserInfo.GroupName;
+               var admin = json.UserInfo.Admin;
+
+               if(result == "SUCCESS")
+               {
+                       sessionStorage.sessionInfoEmail = email;
+                       sessionStorage.sessionInfoName = name;
+                       sessionStorage.sessionInfoGroup = group;
+                       sessionStorage.sessionInfoAdmin = admin;
+                       $.mobile.changePage("#index"); 
+               } 
+               else
+               {
+                       alert(message);
+               }
+       });
+}
+
+function userQueryUserInfo() {
+       queryUserInfo( function (xml) {
+               var email = $(xml).find("Data").find("User").find("Email").text();
+               var name = $(xml).find("Data").find("User").find("Name").text();
+
+               $("#popup-user-info-email").val(email).textinput();
+               $("#popup-user-info-name").val(name).textinput();
+       });
+}
+
+function userModifyUserInfo() {
+       var changeInfoList = [];
+       var changeInfoItem;
+       var email = $('#popup-user-info-email').val();
+       var name = $('#popup-user-info-name').val();
+       var password = $('#popup-user-info-password').val();
+       var password_confirm = $('#popup-user-info-password-confirm').val();
+
+       if(email == ""){
+               alert("Email is invalid");
+               return false;
+       }
+       if(name == ""){
+               alert("Name is invalid");
+               return false;
+       }
+
+       if(password == ""){
+               alert("Password is invalid");
+               return false;
+       }
+
+       if(password != password_confirm){
+               alert("Password is different");
+               return false;
+       }
+
+       changeInfoItem = {"Type":"ModifyUser", "Email":email, "Name":name, "Password":password, "PasswordConfirm":password_confirm};
+       changeInfoList.push(changeInfoItem);
+
+       modifyUserInfo(changeInfoList, function (xml) {
+               alert("Success changed information");
+       });
+}
diff --git a/dibs-web/public/log.html b/dibs-web/public/log.html
new file mode 100644 (file)
index 0000000..ec4c4c4
--- /dev/null
@@ -0,0 +1,114 @@
+<!--
+ log.html
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+-->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <script src="javascripts/jquery-1.7.1.js"></script>
+
+       <script src="javascripts/dibs-api.js"></script>
+       <script src="javascripts/session.js"></script>
+       <script src="javascripts/log.js"></script>
+       <style>
+               body {
+                       margin: 0;
+                       border: none;
+                       padding: 0;
+                       overflow:scroll;
+                       overflow:auto;
+               }
+               #header {
+                       border: solid 1px;
+                       height: 28px;
+                       width: 100%;
+                       padding: 0;
+                       background-color: yellow;
+                       position:fixed;
+                       z-index: 9;
+                       vertical-align:middle
+               }
+               .job-info {
+                       height: 26px;
+                       position: relative;
+                       top: 7px;
+                       left: 5px;
+                       font-size: 12px;
+                       float: left;
+                       vertical-align:middle
+               }
+               .job-info-data {
+                       
+               }
+               #job-info-cancel {
+                       position: absolute;
+                       right:10px;
+               }
+               #body {
+                       position: absolute;
+                       top: 30px;
+                       width: 100%;
+               }
+       </style>
+</head>
+
+<body>
+       <div id="header">
+               <div class="job-info" style="width: 120px;">
+                       <span>Job ID: </span>
+                       <strong><span id="job-info-id" class="job-info-data"></span></strong>
+               </div>
+               <div class="job-info" style="width: 200px;">
+                       <span>Distribution: </span>
+                       <strong><span id="job-info-distribution" class="job-info-data"></span></strong>
+               </div>
+               <div class="job-info" style="width: 200px;">
+                       <span>Project: </span>
+                       <strong><span id="job-info-project" class="job-info-data"></span></strong>
+               </div>
+               <div class="job-info" style="width: 200px; display:none;">
+                       <span>Builder: </span>
+                       <strong><span id="job-info-builder" class="job-info-data"></span></strong>
+               </div>
+               <div class="job-info" style="width: 200px;">
+                       <span>Status: </span>
+                       <strong><span id="job-info-status" class="job-info-data"></span></strong>
+               </div>
+               <div id="job-info-cancel" data-mini="true">
+                       <input type="button" data-mini="true" value="CANCEL" onClick=cancelJob() / > 
+               </div>
+       </div>
+       <div id="body">
+               <table id="logTable" style="width: 100%; border: #000000 1px solid; font-size:9pt">
+               </table> 
+       <div id="footer" data-role="controlgroup" data-mini="true" data-type="horizontal">
+               <input type="button" value="More" onClick=moreLog() / > 
+               <input type="button" value="Stop" onClick=stopLog() / > 
+       </div>
+</body>
+</html>
+
diff --git a/dibs-web/public/robots.txt b/dibs-web/public/robots.txt
new file mode 100644 (file)
index 0000000..085187f
--- /dev/null
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-Agent: *
+# Disallow: /
diff --git a/dibs-web/public/stylesheets/application.css b/dibs-web/public/stylesheets/application.css
new file mode 100644 (file)
index 0000000..3192ec8
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
diff --git a/dibs-web/public/stylesheets/images/ajax-loader.gif b/dibs-web/public/stylesheets/images/ajax-loader.gif
new file mode 100644 (file)
index 0000000..fd1a189
Binary files /dev/null and b/dibs-web/public/stylesheets/images/ajax-loader.gif differ
diff --git a/dibs-web/public/stylesheets/images/ajax-loader.png b/dibs-web/public/stylesheets/images/ajax-loader.png
new file mode 100644 (file)
index 0000000..13b208d
Binary files /dev/null and b/dibs-web/public/stylesheets/images/ajax-loader.png differ
diff --git a/dibs-web/public/stylesheets/images/icons-18-black.png b/dibs-web/public/stylesheets/images/icons-18-black.png
new file mode 100644 (file)
index 0000000..ce1b758
Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-18-black.png differ
diff --git a/dibs-web/public/stylesheets/images/icons-18-white.png b/dibs-web/public/stylesheets/images/icons-18-white.png
new file mode 100644 (file)
index 0000000..1ab0127
Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-18-white.png differ
diff --git a/dibs-web/public/stylesheets/images/icons-36-black.png b/dibs-web/public/stylesheets/images/icons-36-black.png
new file mode 100644 (file)
index 0000000..1a59d7c
Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-36-black.png differ
diff --git a/dibs-web/public/stylesheets/images/icons-36-white.png b/dibs-web/public/stylesheets/images/icons-36-white.png
new file mode 100644 (file)
index 0000000..5647bdc
Binary files /dev/null and b/dibs-web/public/stylesheets/images/icons-36-white.png differ
diff --git a/dibs-web/public/upload.html b/dibs-web/public/upload.html
new file mode 100644 (file)
index 0000000..fb2ffb0
--- /dev/null
@@ -0,0 +1,97 @@
+<!--
+ upload.html
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Sungmin Kim <dev.sungmin.kim@samsung.com>
+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
+-->
+
+<head>
+       <script type="text/javascript" src="javascripts/jquery-1.7.1.js"></script>
+</head>
+<body>
+       <form enctype="multipart/form-data">
+               <input name="file" type="file" />
+               <input id="register" type="button" value="Upload" />
+       </form>
+       <progress hidden="hidden"></progress>
+</body>
+</html>
+
+<script>
+$('#register').click(function(){
+       var dist_name = localStorage.distibutionName;
+       var prj_name = localStorage.uploadBinaryProjectName;
+    var formData = new FormData($('form')[0]);
+
+       formData.append("distribution", dist_name);
+       formData.append("project", prj_name);
+
+       $('progress').removeAttr("hidden");
+
+    $.ajax({
+        url: 'projects/binaryFileUpload',  //server script to process data
+        type: 'POST',
+        xhr: function() {  // custom xhr
+            myXhr = $.ajaxSettings.xhr();
+            if(myXhr.upload){ // check if upload property exists
+                myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
+            }
+            return myXhr;
+        },
+        //Ajax events
+        beforeSend: beforeSendHandler,
+        success: completeHandler,
+        error: errorHandler,
+
+        // Form data
+        data: formData,
+
+        //Options to tell JQuery not to process data or worry about content-type
+        cache: false,
+        contentType: false,
+        processData: false
+    });
+});
+
+function beforeSendHandler(e){
+}
+
+function completeHandler(e){
+       alert("Register started! Closed this page");
+
+       //close window
+       window.open('about:blank','_self');
+       opener = window;
+       window.close();
+}
+
+function errorHandler(e){
+}
+
+function progressHandlingFunction(e){
+    if(e.lengthComputable){
+        $('progress').attr({value:e.loaded,max:e.total});
+    }
+}
+</script>
diff --git a/dibs-web/script/rails b/dibs-web/script/rails
new file mode 100755 (executable)
index 0000000..f8da2cf
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+APP_PATH = File.expand_path('../../config/application',  __FILE__)
+require File.expand_path('../../config/boot',  __FILE__)
+require 'rails/commands'
diff --git a/doc/DIBS_Advanced_Guide.pdf b/doc/DIBS_Advanced_Guide.pdf
new file mode 100644 (file)
index 0000000..ae15e40
Binary files /dev/null and b/doc/DIBS_Advanced_Guide.pdf differ
diff --git a/doc/Tizen_SDK_Development_Guide.pdf b/doc/Tizen_SDK_Development_Guide.pdf
new file mode 100644 (file)
index 0000000..f39ba84
Binary files /dev/null and b/doc/Tizen_SDK_Development_Guide.pdf differ
diff --git a/doc/Tizen_SDK_Package_Guide.pdf b/doc/Tizen_SDK_Package_Guide.pdf
new file mode 100644 (file)
index 0000000..b9d966e
Binary files /dev/null and b/doc/Tizen_SDK_Package_Guide.pdf differ
index 7ff849a23ed9c365cf151838c61a91d9456df549..8264341c43caf734fe4f11199ce4407f5135294a 100755 (executable)
@@ -15,20 +15,12 @@ build()
 # install
 install() 
 {
-       BIN_DIR=$SRCDIR/package/dibs.package.${BUILD_TARGET_OS}/data/dev_tools
-       DOC_DIR=$SRCDIR/package/dibs.package.${BUILD_TARGET_OS}/data/dev_tools/doc
+       BIN_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/tools/dibs/
        mkdir -p $BIN_DIR
-       mkdir -p $DOC_DIR
        cp -f $SRCDIR/pkg-* $BIN_DIR/
        cp -f $SRCDIR/build-* $BIN_DIR/
        cp -rf $SRCDIR/src $BIN_DIR/
-       cp -rf $SRCDIR/src $BIN_DIR/
-       cp -f $SRCDIR/AUTHORS $DOC_DIR/
-       cp -f $SRCDIR/LICENSE $DOC_DIR/
-       cp -f $SRCDIR/NOTICE $DOC_DIR/
+       cp -rf $SRCDIR/dibs-web $BIN_DIR/
+       cp -f $SRCDIR/upgrade $BIN_DIR/
+       echo $VERSION > $BIN_DIR/VERSION
 }
-
-
-$1
-echo "$1 success"
-
diff --git a/package/build.macos b/package/build.macos
new file mode 100755 (executable)
index 0000000..8264341
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh -xe
+# clean
+clean()
+{
+       rm -rf $SRCDIR/*.zip
+       rm -rf $SRCDIR/*.tar.gz
+}
+
+# build
+build() 
+{
+       echo "build"
+}
+
+# install
+install() 
+{
+       BIN_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/tools/dibs/
+       mkdir -p $BIN_DIR
+       cp -f $SRCDIR/pkg-* $BIN_DIR/
+       cp -f $SRCDIR/build-* $BIN_DIR/
+       cp -rf $SRCDIR/src $BIN_DIR/
+       cp -rf $SRCDIR/dibs-web $BIN_DIR/
+       cp -f $SRCDIR/upgrade $BIN_DIR/
+       echo $VERSION > $BIN_DIR/VERSION
+}
diff --git a/package/build.windows b/package/build.windows
new file mode 100755 (executable)
index 0000000..8264341
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh -xe
+# clean
+clean()
+{
+       rm -rf $SRCDIR/*.zip
+       rm -rf $SRCDIR/*.tar.gz
+}
+
+# build
+build() 
+{
+       echo "build"
+}
+
+# install
+install() 
+{
+       BIN_DIR=$SRCDIR/package/dibs.package.${TARGET_OS}/data/tools/dibs/
+       mkdir -p $BIN_DIR
+       cp -f $SRCDIR/pkg-* $BIN_DIR/
+       cp -f $SRCDIR/build-* $BIN_DIR/
+       cp -rf $SRCDIR/src $BIN_DIR/
+       cp -rf $SRCDIR/dibs-web $BIN_DIR/
+       cp -f $SRCDIR/upgrade $BIN_DIR/
+       echo $VERSION > $BIN_DIR/VERSION
+}
diff --git a/package/changelog b/package/changelog
new file mode 100644 (file)
index 0000000..2ccd4aa
--- /dev/null
@@ -0,0 +1,109 @@
+* 2.0.10
+- hot fix No method error
+== hyoun jiil <jiil.hyoun@samsung.com> 2013-01-23
+* 2.0.9
+- several bug fix
+-- sync bug fix
+== hyoun jiil <jiil.hyoun@samsung.com> 2013-01-21
+* 2.0.8
+- WEB
+-- Update new job list and job's status in JOBS page.
+-- Update added job log and job's status in JOBS LOG page.
+== sungmin kim <dev.sungmin.kim@samsung.com> 2012-12-12
+* 2.0.7
+- several bug fix
+- Add distribution to upgrade commnad
+- WEB
+-- Fixed bug about request url include dot
+-- Support browser about IE9
+-- Add loading event (spinner)
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-12-24
+* 2.0.6
+- several internal bug fix
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-12-24
+* 2.0.5
+- Upgraded protocol version to 1.7.0
+- Fixed Sign Up bug on WEB
+- Fixed Job group filtering on WEB
+- Fixed User Delete on WEB
+== donghee yang <donghee.yang@samsung.com> 2012-12-14
+* 2.0.4
+- Fixed below bug again 
+== donghee yang <donghee.yang@samsung.com> 2012-12-12
+* 2.0.3
+- fixed bug about web, build-cli query
+== donghee yang <donghee.yang@samsung.com> 2012-12-12
+* 2.0.2
+- fixed bug about web, build-cli query
+== sungmin kim <dev.sungmin.kim@samsung.com> 2012-12-12
+* 2.0.1
+- fixed build.os
+== sungmin kim <dev.sungmin.kim@samsung.com> 2012-12-12
+* 2.0.0
+- DIBS web added.
+== sungmin kim <dev.sungmin.kim@samsung.com> 2012-12-12
+* 1.2.20
+- display distribution when query 
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-11-29
+* 1.2.19
+- Fixed remote build bug and undefined method bug
+== donghee yang <donghee.yang@samsung.com> 2012-11-29
+* 1.2.18
+- Fixed "cancel" operation of remote job
+== donghee yang <donghee.yang@samsung.com> 2012-11-29
+* 1.2.17
+- change dir seperator when windows remove script execute
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-11-28
+* 1.2.16
+- Increased communication timeout to 120sec
+== donghee yang <donghee.yang@samsung.com> 2012-11-28
+* 1.2.15
+- Increased communication timeout to 60sec
+== donghee yang <donghee.yang@samsung.com> 2012-11-28
+* 1.2.14
+- Applied basic job priority 
+- Old job directory will be cleaned when restart
+== donghee yang <donghee.yang@samsung.com> 2012-11-28
+* 1.2.13
+- multi-build can passing --noreverse option
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-10-29
+* 1.2.12
+- Change log on working package server
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-10-29
+* 1.2.10
+- Change log support
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-10-29
+* 1.2.9
+- Added distribution lock
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-18
+* 1.2.8
+- Fixed "cancel" bug
+- Changed to remain logss about communication errors
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-18
+* 1.2.7
+- Fixed a bug that reverse build choose wrong distribution project
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-17
+* 1.2.6
+- Increase TimeOut to 30 sec
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-17
+* 1.2.5
+- Fixed a bug that pkg-build is not working
+- Fixed some bugs when using ruby1.9.1
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-17
+* 1.2.4
+- Fixed a bug that "upgrade" of sub servers are not done
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-16
+* 1.2.3
+- Set "wget" retry count to 3
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-16
+* 1.2.2
+- Fixed server log contents
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-16
+* 1.2.1
+- Fixed some bugs : upgrade, parse error handling, pkg-build, remote job cancel
+== hyoun jiil <jiil.hyoun@samsung.com> 2011-10-16
+* 1.2.0
+- change log support
+- db support
+- multiple distribution support
+== hyoun jiil <jiil.hyoun@samsung.com> 2012-10-16
index 3e172a3e606d9ca309dd3d59452c195d61769a5f..60bd43c4c607b504ef1998582b9bcfa57ccc4549 100644 (file)
@@ -1,15 +1,8 @@
-Package : dibs
-Version : 0.20.7
-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
+Version :2.0.10
+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
-Version : 0.20.7
-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
-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..dbfad2649b862d402e311cf04415cbbbddc2dd74 100755 (executable)
--- a/pkg-build
+++ b/pkg-build
@@ -1,7 +1,7 @@
-#!/usr/bin/ruby 
+#!/usr/bin/ruby
 
 =begin
+
  pkg-build
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -36,51 +36,59 @@ require "packageServer"
 require "Builder"
 require "optionparser"
 
-option = parse
+begin
+       option = parse
+rescue => e
+       puts e.message
+       exit 0
+end
 
 #generate server when local package server is not set
 
+# check HOST OS
+if not Utils.check_host_OS() then
+       puts "Error: Your host OS is not supported!"
+       exit 1
+end
+
 # if "--os" is not specified, use host os type
 if option[:os].nil? then
        option[:os] = Utils::HOST_OS
-else 
-    if not option[:os] =~ /^(linux|windows|darwin)$/ then 
-        puts "We have no plan to Buld OS \"#{option[:os]}\" \n please check your option OS "
-        exit 1
-    end
 end
 
 path = Dir.pwd
-if not File.exist? "package" then 
-    puts "current dirctory \"#{path}\" is not package root directory"
-    exit 1
-end 
+if not File.exist? "package" then
+       puts "current dirctory \"#{path}\" is not package root directory"
+       exit 1
+end
 
 # if url specified
 if not option[:url].nil? then
        begin
-       builder = Builder.get("default") 
+               builder = Builder.get("default")
                if builder.pkgserver_url != option[:url] then
                        puts "Package server URL has been changed! Creating new builder..."
-               builder = Builder.create("default", option[:url], nil)  
+                       builder = Builder.create("default", option[:url], nil, nil, nil)
                end
        rescue
                puts "Default builder does not exist! Creating new builder..."
-       builder = Builder.create("default", option[:url], nil)  
+               builder = Builder.create("default", option[:url], nil, nil, nil)
        end
 else # if url is not specified
-       begin 
-       builder = Builder.get("default")  
+       begin
+               builder = Builder.get("default")
        rescue
                puts "Default builder does not exist! Creating new builder..."
-       builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil)  
+               builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil, nil, nil)
        end
-end 
+end
 
 #build project
-if not builder.build( Utils::WORKING_DIR, option[:os], option[:clean], option[:rev], [], []) then
+if not builder.build( Utils::WORKING_DIR, option[:os], option[:clean], [], true) then
        puts "Build Failed!"
+       exit 1
 else
        puts "Build Succeeded!"
+       exit 0
 end
 
index de48dce4047eda5929f71b6c07f935b65f872c2e..6a6cbb405b91ebb3734ed7f0a2de54f7fa42c481 100755 (executable)
--- a/pkg-clean
+++ b/pkg-clean
@@ -1,7 +1,7 @@
-#!/usr/bin/ruby 
+#!/usr/bin/ruby
 
 =begin
+
  pkg-clean
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -37,20 +37,26 @@ require "Builder"
 require "CleanOptionParser"
 
 path = Dir.pwd
-if not File.exist? "package" then 
-    puts "current dirctory \"#{path}\" is not package root directory"
-    exit 1
-end 
+if not File.exist? "package" then
+       puts "current dirctory \"#{path}\" is not package root directory"
+       exit 1
+end
 
 option = parse
 
 #generate server when local package server is not set
 
-begin 
-       builder = Builder.get("default")  
+# check HOST OS
+if not Utils.check_host_OS() then
+       puts "Error: Your host OS is not supported!"
+       exit 1
+end
+
+begin
+       builder = Builder.get("default")
 rescue
        puts "Default builder does not exist! Creating new builder..."
-       builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil)  
+       builder = Builder.create("default", "http://172.21.111.132/pkgserver/unstable",nil)
 end
 
 #build project
diff --git a/pkg-cli b/pkg-cli
index 2e0f21e1ac66162b3c1d98ad1fca748892529823..f2d2e8b36f7788c75754010cfa6254ca230dc345 100755 (executable)
--- a/pkg-cli
+++ b/pkg-cli
@@ -1,7 +1,7 @@
-#!/usr/bin/ruby 
+#!/usr/bin/ruby
 
 =begin
+
  pkg-cli
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -42,137 +42,119 @@ require "packageServer"
 #set global variable
 @WORKING_DIR = nil
 
-$log = Logger.new('.log', 'monthly')
-
-#option parsing 
+#option parsing
 begin
        option = option_parse
 rescue => e
        # if option parse error print help message
-    $log.error "option parsing error"
-       system "#{__FILE__} help"
+       puts e.message
        exit 0
 end
 
+# check HOST OS
+if not Utils.check_host_OS() then
+       puts "Error: Your host OS is not supported!"
+       exit 1
+end
 #if "--os" is not specfied, use host os type
 if option[:os].nil? then
-       system_type = `uname -s`
-       case system_type.strip
-    when "Linux" then
-               option[:os] = "linux"
-       when /MINGW32.*/ then
-               option[:os] = "windows"
-       when "Darwin" then
-               option[:os] = "darwin"
-       else
-               raise RuntimeError, "Unknown OS type : #{system_type}"
-       end
+       option[:os] = Utils::HOST_OS
 end
 
-case option[:cmd] 
+case option[:cmd]
 when "update" then
-    client = Client.new( option[:url], nil, nil )
-    client.update()
+       client = Client.new( option[:url], nil, nil )
+       #client.update()
 when "clean" then
-    client = Client.new( nil, option[:loc], nil )
-    client.clean(option[:f])
+       client = Client.new( nil, option[:loc], nil )
+       client.clean(option[:f])
 when "download" then
-    client = Client.new( option[:url], option[:loc], nil )
-    if not option[:url].nil? then
-        client.update()
-    end
+       client = Client.new( option[:url], option[:loc], nil )
+       #if not option[:url].nil? then
+       #    client.update()
+       #end
        file_loc = client.download( option[:pkg], option[:os], option[:t] )
-when "upload" then
-    client = Client.new( nil, nil, nil )
-       result = client.upload( option[:alias], option[:id], option[:binpkg], option[:srcpkg], false )
-    if not result.nil? then
-        puts result
-    end
-when "source" then    
-    client = Client.new( option[:url], option[:loc], nil )
-    if not option[:url].nil? then
-        client.update()
-    end
-    client.download_source( option[:pkg], option[:os] )
 when "install" then
-    client = Client.new( option[:url], option[:loc], nil )
-    if not option[:url].nil? then
-        client.update()
-    end
-       client.install( option[:pkg], option[:os], option[:t], option[:f] ) 
+       client = Client.new( option[:url], option[:loc], nil )
+       #if not option[:url].nil? then
+       #    client.update()
+       #end
+       client.install( option[:pkg], option[:os], option[:t], option[:f] )
 when "install-file" then
-    client = Client.new( nil, option[:loc], nil )
-       client.install_local_pkg( option[:pkg], option[:f] ) 
+       client = Client.new( option[:url], option[:loc], nil )
+       client.install_local_pkg( option[:pkg], option[:t], option[:f] )
 when "uninstall" then
-    client = Client.new( nil, option[:loc], nil )
-    client.uninstall( option[:pkg], option[:t] )
+       client = Client.new( nil, option[:loc], nil )
+       client.uninstall( option[:pkg], option[:t] )
 when "upgrade" then
-    client = Client.new( option[:url], option[:loc], nil )
-    if not option[:url].nil? then
-        client.update()
-    end
-    client.upgrade( option[:os], option[:t] )
+       client = Client.new( option[:url], option[:loc], nil )
+       #if not option[:url].nil? then
+       #    client.update()
+       #end
+       client.upgrade( option[:os], option[:t] )
 when "check-upgrade" then
-    client = Client.new( option[:url], option[:loc], nil )
-    if not option[:url].nil? then
-        client.update()
-    end
-    client.check_upgrade( option[:os] )
+       client = Client.new( option[:url], option[:loc], nil )
+       #if not option[:url].nil? then
+       #   client.update()
+       #end
+       client.check_upgrade( option[:os] )
 when "show-rpkg" then
-    client = Client.new( option[:url], nil, nil )
-    if not option[:url].nil? then
-        client.update()
-    end
-       puts client.show_pkg_info( option[:pkg], option[:os] ) 
+       client = Client.new( option[:url], nil, nil )
+       #if not option[:url].nil? then
+       #    client.update()
+       #end
+       puts client.show_pkg_info( option[:pkg], option[:os] )
 when "list-rpkg" then
-    client = Client.new( option[:url], nil, nil )
-    if not option[:url].nil? then
-        client.update()
-    end
+       client = Client.new( option[:url], nil, nil )
+       #if not option[:url].nil? then
+       #    client.update()
+       #end
        result = client.show_pkg_list( option[:os] )
-    if not result.nil? and not result.empty? then
-        result.each do |i|
-            name = i[0].strip
-            version = i[1].strip
-            desc = i[2].strip
-            puts name + "  (" + version + ")"
-        end
-    end
+       if not result.nil? and not result.empty? then
+               result.each do |i|
+                       name = i[0].strip
+                       version = i[1].strip
+                       desc = i[2].strip
+                       puts name + "  (" + version + ")"
+               end
+       end
 when "show-lpkg" then
-    client = Client.new( nil, option[:loc], nil )
-    puts client.show_installed_pkg_info( option[:pkg] )
+       client = Client.new( nil, option[:loc], nil )
+       puts client.show_installed_pkg_info( option[:pkg] )
 when "list-lpkg" then
-    client = Client.new( nil, option[:loc], nil )
+       client = Client.new( nil, option[:loc], nil )
        result = client.show_installed_pkg_list()
-    if not result.nil? and not result.empty? then
-        result.each do |i|
-            name = i[0].strip
-            version = i[1].strip
-            desc = i[2].strip
-            puts name + "  (" + version + ")"
-        end
-    end
+       if not result.nil? and not result.empty? then
+               result.each do |i|
+                       name = i[0].strip
+                       version = i[1].strip
+                       desc = i[2].strip
+                       puts name + "  (" + version + ")"
+               end
+       else
+               puts "Info: There is no any package."
+       end
 when "build-dep" then
-    client = Client.new( nil, nil, nil )
+       client = Client.new( nil, nil, nil )
        result = client.get_build_dependent_packages( option[:pkg], option[:os], true )
-    ret = ""
-    result.each do |i|
-        ret = ret + i + " --> "
-    end
-    ret = ret.strip
-    ret[-3..-1] = ""
-    puts ret
+       ret = ""
+       result.each do |i|
+               ret = ret + i + " --> "
+       end
+       ret = ret.strip
+       ret[-3..-1] = ""
+       puts ret
 when "install-dep" then
-    client = Client.new( nil, nil, nil )
+       client = Client.new( nil, nil, nil )
        result = client.get_install_dependent_packages( option[:pkg], option[:os], true, false )
-    ret = ""
-    result.each do |i|
-        ret = ret + i + " --> "
-    end
-    ret = ret.strip
-    ret[-3..-1] = ""
-    puts ret
+       ret = ""
+       result.each do |i|
+               ret = ret + i + " --> "
+       end
+       ret = ret.strip
+       ret[-3..-1] = ""
+       puts ret
 else
-       raise RuntimeError, "input option incorrect : #{option[:cmd]}"
+       raise RuntimeError, "Input is incorrect : #{option[:cmd]}"
 end
 
diff --git a/pkg-svr b/pkg-svr
index 3cf41212b813fa903ff0df362335369e6f41b50e..6c50176b185663a0af72db2c307d4e15c18bc608 100755 (executable)
--- a/pkg-svr
+++ b/pkg-svr
@@ -1,7 +1,7 @@
-#!/usr/bin/ruby 
+#!/usr/bin/ruby
 
 =begin
+
  pkg-svr
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -35,67 +35,84 @@ require "utils"
 require "packageServer"
 require "serverOptParser"
 
-#option parsing 
+#option parsing
 begin
        option = option_parse
 rescue => e
-       puts "\n=============== Error occured =============================="
        puts e.message
-       puts e.backtrace.inspect
-       puts "=============================================================\n"
        exit 0
 end
 
-begin 
+begin
        if option[:cmd].eql? "list" then
                if option[:id].empty? then
-                       PackageServer.list_id 
+                       PackageServer.list_id
                else
                        PackageServer.list_dist option[:id]
-               end 
-               exit 
-       end 
+               end
+               exit
+       end
 
        server = PackageServer.new( option[:id] )
 
-       if server.nil? 
+       if server.nil?
                raise RuntimeError, "server class creation fail"
        end
 
-       case option[:cmd] 
-       when "create"  
+       case option[:cmd]
+       when "create"
                server.create( option[:id], option[:dist], option[:url], option[:loc] )
        when "register"
-               server.register( option[:spkgs], option[:bpkgs], option[:dist], option[:gensnap], option[:test] ) 
+               server.register( option[:pkgs], option[:dist], option[:gensnap], option[:test], false )
        when "gen-snapshot"
-               server.generate_snapshot( option[:snap], option[:dist], option[:bsnap], option[:bpkgs] ) 
+               server.generate_snapshot( option[:snaps][0], option[:dist], option[:bsnap] )
        when "sync"
-               server.sync( option[:dist], option[:force] )
+               server.sync( option[:dist], option[:force], option[:snaps][0] )
        when "add-dist"
                server.add_distribution( option[:dist], option[:url], option[:clone] )
-       when "spkg-path" 
-               server.find_source_package_path( option[:dist], option[:spkgs] )
+       when "add-os"
+               server.add_os( option[:dist], option[:os] )
        when "remove"
-               puts  "Do you want to really? then input \"YES\""
-               input = $stdin.gets.strip
-               if input.eql? "YES" then   
-                       puts "Remove server!"
-               else
-                       puts "Remove is canceled by user input"
-                       exit(0)
+               if not option[:force] then
+                       puts  "Do you want to really? then input \"YES\""
+                       input = $stdin.gets.strip
+                       if input.eql? "YES" then
+                               puts "Remove server!"
+                       else
+                               puts "Remove is canceled by user input"
+                               exit(0)
+                       end
+               end
+
+               server.remove_server()
+       when "remove-dist"
+               if not option[:force] then
+                       puts  "Do you want to really? then input \"YES\""
+                       input = $stdin.gets.strip
+                       if input.eql? "YES" then
+                               puts "Remove server!"
+                       else
+                               puts "Remove is canceled by user input"
+                               exit(0)
+                       end
                end
 
-               server.remove_server( option[:id] )
+               server.remove_dist( option[:dist] )
        when "remove-pkg"
-               server.remove_pkg( option[:id], option[:dist], option[:bpkgs] )
+               server.remove_pkg( option[:dist], option[:pkgs], option[:os] )
+       when "remove-snapshot"
+               server.remove_snapshot( option[:dist], option[:snaps] )
+       when "clean"
+               server.clean( option[:dist], option[:snaps] )
+       when "start"
+               server.start( option[:port], option[:passwd] )
+       when "stop"
+               server.stop( option[:port], option[:passwd] )
        else
                raise RuntimeError, "input option incorrect : #{option[:cmd]}"
        end
-rescue => e 
-       puts "\n=============== Error occured =============================="
+rescue => e
        puts e.message
-       puts e.backtrace.inspect
-       puts "=============================================================\n"
 end
 
 
diff --git a/src/build_server/BinaryUploadProject.rb b/src/build_server/BinaryUploadProject.rb
new file mode 100644 (file)
index 0000000..f653b80
--- /dev/null
@@ -0,0 +1,200 @@
+=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'
+require 'dbi'
+$LOAD_PATH.unshift File.dirname(__FILE__)
+require "CommonProject.rb"
+require "RegisterPackageJob.rb"
+require "Version.rb"
+require "PackageManifest.rb"
+
+
+class BinaryUploadProject < CommonProject
+       attr_accessor :pkg_name
+
+       # initialize
+       def initialize( name, server, os_list, dist_name, pkg_name = nil )
+               super(name, "BINARY", server, os_list, dist_name)
+               @pkg_name = pkg_name
+       end
+
+
+       # create new job
+       def create_new_job( filename, dock = "0" )
+               file_path = "#{@server.transport_path}/#{dock}/#{filename}"
+               new_job = create_new_job_from_local_file( file_path )
+               if not new_job.nil? then
+                       new_job.set_auto_remove(true)
+               end
+
+               return new_job
+       end
+
+
+       def create_new_job_from_local_file( file_path )
+               filename = File.basename(file_path) 
+               new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+               pkg_name = new_name.split(",")[0]
+               os = new_name.split(",")[2]
+
+               # check file name
+               if @pkg_name != pkg_name then
+                       @server.log.error( "registed name is #{@pkg_name} not #{pkg_name} !", Log::LV_USER)
+                       return nil
+               end
+
+               # check os name
+               if not @server.supported_os_list.include? os then
+                       @server.log.error( "server not support OS : #{os}", Log::LV_USER)
+                       return nil
+               end
+
+               # check package info
+               if not File.exist? file_path then
+                       @server.log.error( "file not exists in #{file_path}", Log::LV_USER)
+                       return nil
+               end
+
+               pkginfo_dir = "#{@path}/pkginfos"
+               if not File.exist? pkginfo_dir then FileUtils.mkdir_p pkginfo_dir end
+               if not Utils.extract_a_file(file_path, "pkginfo.manifest", pkginfo_dir) then
+                       @server.log.error( "pkginfo.manifest file is not exist", Log::LV_USER)
+                       return nil
+               end
+               begin
+                       pkginfo =PackageManifest.new("#{pkginfo_dir}/pkginfo.manifest")
+               rescue => e
+                       @server.log.error( e.message, Log::LV_USER)
+                       return nil
+               end
+
+               ##set up change log
+               #change_log = {}
+               #begin
+               #       change_log = Parser.read_changelog "#{pkginfo_dir}/changelog" if File.exist? "#{pkginfo_dir}/changelog"
+               #rescue => e
+               #       @server.log.error( e.message, Log::LV_USER)
+               #       return nil
+               #end
+
+               #if not change_log.empty? and pkginfo.packages[0].change_log.empty? then
+               #       pkginfo.packages.each {|pkg| pkg.change_log = change_log}
+               #end
+
+               #if @server.changelog_check and not pkginfo.packages[0].does_change_exist? then
+               #       @server.log.error( "change log not found", Log::LV_USER)
+               #       return nil
+               #end
+
+               pkgs =  pkginfo.get_target_packages(os)
+               if pkgs.count != 1 then
+                       @server.log.error( "only one package can upload at one time", Log::LV_USER)
+                       return nil
+               end
+               if pkgs[0].package_name != @pkg_name then
+                       @server.log.error( "package name is #{pkgs[0].package_name} not #{@pkg_name}", Log::LV_USER)
+                       return nil
+               end
+
+               new_job = RegisterPackageJob.new( file_path, self, @server, nil, @dist_name )
+       end
+
+
+       def self.create_table(db, post_fix)
+               db.do "CREATE TABLE project_bins ( 
+                       project_id INTEGER NOT NULL, 
+                       pkg_name VARCHAR(32) NOT NULL,
+                       PRIMARY KEY ( project_id ),
+                       CONSTRAINT fk_project_bins_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ) )#{post_fix}"
+       end
+
+
+       def self.load(name, dist_name, server, db)
+               row, prj_os_list, source_info, package_info = load_row(name, dist_name, db)
+               prj_id = row['id']
+               prj_name = row['name']
+               prj_passwd = row['password']
+
+               new_project = BinaryUploadProject.new(prj_name, server, prj_os_list, dist_name)
+               if not prj_passwd.empty? then new_project.passwd = prj_passwd end
+               new_project.set_project_id( prj_id )
+               new_project.set_source_info( source_info )
+               new_project.set_package_info( package_info )
+
+               row=db.select_one("SELECT * FROM project_bins WHERE project_id=#{prj_id}")
+               if row.nil? then return nil end
+               new_project.pkg_name=row['pkg_name']
+
+               return new_project
+       end
+
+
+       def save(db)
+               is_new = save_common(db)
+               init()
+
+               if is_new then
+                       db.do "INSERT INTO project_bins VALUES (#{@prj_id},'#{@pkg_name}')"
+                       db.do "INSERT INTO group_project_accesses 
+                               VALUES ( (SELECT groups.id FROM groups WHERE groups.name = 'admin'),'#{@prj_id}','TRUE')"
+               else
+                       db.do "UPDATE project_bins SET pkg_name='#{@pkg_name}' WHERE project_id=#{@prj_id})"
+               end
+       end
+
+
+       def save_source_info(ver,info)
+               @server.get_db_connection() do |db|
+                       save_source_info_internal(ver,info, db)
+               end
+       end
+
+
+       # save package info
+       def save_package_info_from_manifest(version, file_path, os)
+               begin
+                       pkginfo =PackageManifest.new(file_path)
+               rescue => e
+                       @server.log.error e.message
+                       return
+               end
+
+               pkginfo.get_target_packages(os).each do |pkg|
+                       save_package_info(pkg.version, pkg.package_name, os)
+               end
+       end
+
+
+       def unload(db)
+               unload_common(db)
+               if @prj_id != -1 then
+                       db.do "DELETE FROM project_bins WHERE project_id=#{@prj_id}"
+               end
+       end
+end
index 79941ca41b54d5b0e0d9e010b50532d2029c419d..63fb3da215e59ee23b62ca2154c3a91b35acc503 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- BuildClientOptionParser.rb 
+
+ BuildClientOptionParser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -26,72 +26,204 @@ Contributors:
 - S-Core Co., Ltd
 =end
 
+$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 require 'optparse'
+require 'utils'
+
+class BuildClientUsage
+       BUILD="build-cli build -N <project name> -d <server address> [-o <os>] [-w <password>] [--async] [-D <distribution name>] [-U user-email] [-V]"
+       RESOLVE="build-cli resolve -N <project name> -d <server address> [-o <os>] [-w <password>] [--async] [-D <distribution name>] [-U user-email] [-V]"
+       QUERY="build-cli query -d <server address>"
+       QUERY_SYSTEM="build-cli query-system -d <server address>"
+       QUERY_PROJECT="build-cli query-project -d <server address>"
+       QUERY_JOB="build-cli query-job -d <server address>"
+       CANCEL="build-cli cancel -j <job number> -d <server address> [-w <password>] [-U user-email]"
+       REGISTER="build-cli register -P <package file> -d <server address>  [-t <ftp server url>] [-w <password>] [-D <distribution name>] [-U user-email]"
+end
+
+
+def option_error_check( options )
+       case options[:cmd]
+
+       when "build" then
+               if options[:project].nil? or options[:project].empty? or
+                       options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::BUILD
+               end
+
+       when "resolve" then
+               if options[:project].nil? or options[:project].empty? or
+                       options[:domain].nil?  or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::RESOLVE
+               end
+
+       when "query" then
+               if options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::QUERY
+               end
+
+       when "query-system" then
+               if options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::QUERY_SYSTEM
+               end
+
+       when "query-project" then
+               if options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::QUERY_PROJECT
+               end
+
+       when "query-job" then
+               if options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::QUERY_JOB
+               end
 
-def option_parse 
-    options = {}
-    banner = "Usage: build-cli {build|resolve|query} ..." + "\n" \
-               + "\t" + "build-cli build -g <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>] [-o <os>] " + "\n" 
-
-    optparse = OptionParser.new do|opts|
-        # Set a banner, displayed at the top
-        # of the help screen.
-
-               opts.banner = banner 
-
-               opts.on( '-g', '--git <git-repository>', 'git repository' ) do|git|
-            options[:git] = git
-        end
-
-               opts.on( '-c', '--commit <git-commit>', 'git commit id/tag' ) do|git|
-            options[:commit] = git
-        end
-
-        options[:domain] = nil
-               opts.on( '-d', '--domain <build-svr-domain>', 'remote build server ip address. default 172.21.111.177' ) do|domain|
-            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
-               opts.on( '-o', '--os <operating system>', 'target operating system linux/windows/darwin' ) do|os|
-            options[:os] = os
-        end
-
-        options[:async] = "NO"
-               opts.on( '-a', '--async', 'asynchronous job' ) do
-            options[:async] = "YES"
-        end
-       
-               opts.on( '-h', '--help', 'display this information' ) do
-            puts opts
+       when "cancel" then
+               if options[:job].nil? or options[:job].empty? or
+                       options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::CANCEL
+               end
+       when "register" then
+               if options[:package].nil? or options[:package].empty? or
+                       options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildClientUsage::REGISTER
+               end
+
+       else
+               raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
+       end
+
+       if ARGV.length > 1 then
+               raise ArgumentError, "Unknown argument value : #{ARGV[1]}"
+       end
+end
+
+def option_parse
+       options = {}
+       banner = "Requiest service to build-server command-line tool." + "\n" \
+               + "\n" + "Usage: build-cli <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" + BuildClientUsage::BUILD + "\n" \
+               + "\t" + BuildClientUsage::RESOLVE + "\n" \
+               + "\t" + BuildClientUsage::QUERY + "\n" \
+               + "\t" + BuildClientUsage::QUERY_SYSTEM + "\n" \
+               + "\t" + BuildClientUsage::QUERY_PROJECT + "\n" \
+               + "\t" + BuildClientUsage::QUERY_JOB + "\n" \
+               + "\t" + BuildClientUsage::CANCEL + "\n" \
+               + "\t" + BuildClientUsage::REGISTER + "\n" \
+               + "\n" + "Options:" + "\n"
+
+       optparse = OptionParser.new(nil, 32, ' '*8) do|opts|
+
+               # Set a banner, displayed at the top
+               # of the help screen.
+
+               opts.banner = banner
+
+               opts.on( '-N', '--project <project name>', 'project name' ) do|project|
+                       if not Utils.multi_argument_test( project, "," ) then
+                               raise ArgumentError, "Project variable parsing error : #{project}"
+                       end
+                       options[:project] = project
+               end
+
+               options[:domain] = nil
+               opts.on( '-d', '--address <server address>', 'build server address: 127.0.0.1:2224' ) do|domain|
+                       options[:domain] = domain
+               end
+
+               options[:os] = nil
+               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"
+               opts.on( '--async', 'asynchronous job' ) do
+                       options[:async] = "YES"
+               end
+
+               options[:noreverse] = "NO"
+               opts.on( '--noreverse', 'do not check reverse build' ) do
+                       options[:noreverse] = "YES"
+               end
+
+               opts.on( '-j', '--job <job number>', '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( '-D', '--dist <distribution name>', 'distribution name' ) do|dist|
+                       options[:dist] = dist
+               end
+
+               opts.on( '-t', '--ftp <ftp server url>', 'ftp server url: ftp://dibsftp:dibsftp@127.0.0.1' ) do|domain|
+                       options[:fdomain] = domain
+               end
+
+               options[:user] = "admin@user"
+               opts.on( '-U', '--user <user email>', 'user email infomation' ) do|user|
+                       options[:user] = user
+               end
+
+               options[:verbose] = "NO"
+               opts.on( '-V', '--verbose', 'verbose mode' ) do
+                       options[:verbose] = "YES"
+               end
+
+               opts.on( '-h', '--help', 'display help' ) do
+                       opts.help.split("\n").each {|op| puts op if not op.include? "--noreverse"}
                        exit
-        end
-               
-    end
-    
-       cmd = ARGV[0] 
+               end
 
-    if cmd.eql? "build" or cmd.eql? "resolve" or cmd.eql? "query" or 
-                cmd =~ /(help)|(-h)|(--help)/ then
+               opts.on( '-v', '--version', 'display version' ) do
+                       puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
+                       exit
+               end
 
-        if cmd.eql? "help" then 
-                       ARGV[0] = "-h" 
+       end
+
+       cmd = ARGV[0]
+
+       if cmd.eql? "build" or cmd.eql? "resolve" or
+               cmd.eql? "query" or cmd.eql? "query-system" or
+               cmd.eql? "query-project" or cmd.eql? "query-job" or
+               cmd.eql? "cancel" or
+               cmd.eql? "register" or
+               cmd =~ /(-v)|(--version)/ or
+               cmd =~ /(help)|(-h)|(--help)/ then
+
+               if cmd.eql? "help" then
+                       ARGV[0] = "-h"
                end
 
-        options[:cmd] = ARGV[0]
-    else
-        raise ArgumentError, banner
-    end
+               options[:cmd] = ARGV[0]
+       else
+               raise ArgumentError, "Usage: build-cli <SUBCOMMAND> [OPTS] or build-cli -h"
+       end
+
+       optparse.parse!
+
+       option_error_check options
 
-    optparse.parse!
-   
-    return options
-end 
+       return options
+end
 
index 2a7f5c700e7ec90db183c7bc33e2c97ae422fa2a..71c348524f23f25af07a1a0cb1c189fbcfe082fe 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  BuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -35,89 +35,360 @@ require "client.rb"
 require "PackageManifest.rb"
 require "Version.rb"
 require "Builder.rb"
-require "BuildServer.rb"
+require "RemoteBuilder.rb"
 require "JobLog.rb"
 require "mail.rb"
+require "utils.rb"
+require "ReverseBuildChecker.rb"
+require "CommonJob.rb"
 
-class BuildJob
+class BuildJob < CommonJob
 
-       attr_accessor :blocked_by
+       attr_accessor :pkginfo, :source_path
+       attr_accessor :pkgsvr_client, :thread
+       attr_accessor :rev_fail_projects, :rev_success_jobs
+       attr_accessor :pending_ancestor, :cancel_state
+       attr_accessor :no_reverse
+       attr_accessor :remote_id
 
        # initialize
-       def initialize ()
-               @blocked_by = []
+       def initialize (project, os, server)
+               super(server)
+               @project = project
+               @os = os
+               @type = "BUILD"
+
+               @cancel_state = "NONE"
+               @resolve = false
+               @host_os = Utils::HOST_OS
+               if not @server.distmgr.nil? then
+                       @pkgsvr_url = @server.distmgr.get_distribution(project.dist_name).pkgsvr_url
+                       @pkgsvr_ip = @server.distmgr.get_distribution(project.dist_name).pkgsvr_ip
+                       @pkgsvr_port = @server.distmgr.get_distribution(project.dist_name).pkgsvr_port
+               else
+                       @pkgsvr_url = ""
+                       @pkgsvr_ip = ""
+                       @pkgsvr_port = ""
+               end
+               @job_root = "#{@server.path}/jobs/#{@id}"
+               @source_path = @job_root+"/temp"
+               @job_working_dir=@job_root+"/works"
+               @buildroot_dir = "#{@job_root}/buildroot"
+
+               # this item will be initialized on pre-verify
+               @pkginfo = nil
+               @pkgsvr_client = nil
+               @thread = nil
+               @log = nil
+               @parent = nil # for job hierachy
+
+               #for cancel operation
+               @pending_ancestor = nil # for cancel pending job
+               @remote_id = nil # for cancel remote_working job
+               @build_dep_prjs = nil # for cacnel pending job
+
+               # for resolving build-break
+               @rev_fail_projects = [] # list of [project,os]
+               @rev_success_jobs = [] # list of job
+
+               # remote build
+               @remote_server = nil
+
+               # job type
+               @is_rev_build_check_job = false
+               @is_remote_job = false
+
+               # for internal(transferred) job
+               @is_internal_job = false
+               @dock_num = "0"
+
+               @external_pkgs = []
+               @force_rebuild = false
+
+               @no_reverse = false
        end
 
-       # execute
-       def execute
-               @log.info( "Invoking a thread for building Job #{@id}", Log::LV_USER)
-               if @status == "ERROR" then return  end
-               @thread = Thread.new {
-                       # main
-                       thread_main()
-                       
-                       # close 
-                       terminate()
-               } 
+
+       def get_distribution_name()
+               return @project.dist_name
+       end
+
+
+       def get_buildroot()
+               return @buildroot_dir
+       end
+
+
+       # set reverse build check job
+       def set_rev_build_check_job( parent )
+               @is_rev_build_check_job = true
+
+               # if parent exists, share build-root
+               if not parent.nil? then
+                       set_parent_job( parent )
+               end
+       end
+
+
+       def is_rev_build_check_job()
+               return @is_rev_build_check_job
+       end
+
+
+       def set_remote_job(server)
+               @is_remote_job = true
+               @remote_server=server
+       end
+
+
+       def get_remote_server()
+               return @remote_server
+       end
+
+
+       def set_no_reverse()
+               @no_reverse = true
+       end
+
+
+       def set_internal_job( dock_num )
+               @is_internal_job = true
+               @dock_num = dock_num
+       end
+
+
+       # set option for waiting for resolve
+       def set_resolve_flag()
+               @resolve = true
+       end
+
+
+       # set force rebuild
+       # This make project to build
+       # even though there is a package of same version on pkg-server
+       def set_force_rebuild(value)
+               @force_rebuild = value
        end
 
 
-       # remote
-       def execute_remote(server)
-               @log.info( "Invoking a thread for remote-building Job #{@id}", Log::LV_USER)
-               if @status == "ERROR" then return  end
-               @thread = Thread.new {
-                       # main
-                       remote_thread_main( server )
-                       
-                       # close 
-                       terminate()
-               } 
+       # add external packages to overwrite before build
+       def add_external_package( file_name )
+               @external_pkgs.push "#{@job_root}/external_pkgs/#{file_name}"
+       end
+
+
+       #terminate
+       def terminate()
+               #do noting
+       end
+
+
+       #cancel
+       def cancel()
+               # kill sub process if exist?
+               kill_sub_process()
+
+               # cancel all its reverse job
+               @server.jobmgr.reverse_build_jobs.each do |job|
+                       if job.get_parent_job() == self and job.cancel_state == "NONE" then
+                               job.cancel_state = "INIT"
+                       end
+               end
+
+               # cancel log print
+               if not @log.nil? then
+                       @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER)
+               end
+
+               case @status
+               when "REMOTE_WORKING" then
+                       client = BuildCommClient.create( @remote_server.ip, @remote_server.port, @log )
+                       if not client.nil? then
+                               client.send "CANCEL|#{@remote_id}|#{self.get_project.passwd}|admin@user"
+                               result1 = client.receive_data()
+                               if result1.nil? then
+                                       @log.info( "cancel operation failed [connection error] !!", Log::LV_USER)
+                               else
+                                       result1.each do |l|
+                                               @log.info(l, Log::LV_USER)
+                                       end
+                               end
+                               client.terminate
+                       end
+               when "PENDING" then
+                       if @pending_ancestor.nil? then
+                               #resolve pending job
+                               pending_descendants = @server.jobmgr.jobs.select do |j|
+                                       (not j.pending_ancestor.nil?) and "#{j.pending_ancestor.id}" == "#{@id}"
+                               end
+                               pending_descendants.each do |pd|
+                                       pd.cancel_state = "INIT"
+                               end
+                       else
+                               # remove myself from success job if exist
+                               # and add myself into rev_fail_project list if not exist
+                               @pending_ancestor.remove_rev_success_job(self)
+                               @pending_ancestor.add_rev_fail_project( @project, @os )
+
+                               # remove the project that depends on me if exist
+                               # and add it into rev_fail_project list if not exist
+                               p_sub_jobs = @server.jobmgr.jobs.select do |j|
+                                       ( not j.pending_ancestor.nil? and
+                                        "#{j.pending_ancestor.id}" == "#{@pending_ancestor.id}" and
+                                        j.is_build_dependent_project(@project, @os) )
+                               end
+                               p_sub_jobs.each do |d|
+                                       @pending_ancestor.remove_rev_success_job(d)
+                                       @pending_ancestor.add_rev_fail_project( d.get_project, d.os )
+
+                                       if not d.thread.nil? then d.thread.terminate end
+                                       d.status = "WAITING"
+                               end
+                       end
+               when "WORKING", "WAITING" , "INITIALIZING" , "JUST_CREATED" then
+                       #just log
+               else # ERROR | FINISHED | RESOLVED
+                       #do noting
+               end
        end
 
 
        # check building is possible
        def can_be_built_on?(host_os)
-               for pkg in @pkginfo.packages
-                       if pkg.os == @os and pkg.build_host_os.include? host_os then
+               if @pkginfo.nil? then return false end
+
+               @pkginfo.packages.each do |pkg|
+                       if pkg.os_list.include? @os and pkg.build_host_os.include? host_os then
                                return true
                        end
                end
-               
                return false
        end
 
 
+       def get_packages()
+               return @pkginfo.packages
+       end
+
+
+       def get_build_dependencies(target_os)
+               return @pkginfo.get_build_dependencies(target_os)
+       end
+
+
+       def get_source_dependencies(target_os,host_os)
+               return @pkginfo.get_source_dependencies(target_os,host_os)
+       end
+
+
+       def is_compatible_with?(o)
+               # must have same distribution
+               if get_distribution_name() != o.get_distribution_name() then
+                       return false
+               end
+
+               if type != o.type then return false end
+
+               my_project = get_project()
+               other_project = o.get_project()
+
+               # check project name
+               if my_project.nil? or other_project.nil? or
+                       my_project.name != other_project.name then
+                       return false
+               end
+
+               # check version
+               if @pkginfo.nil? or o.pkginfo.nil? or
+                       not(Version.new(@pkginfo.get_version()) == Version.new(o.pkginfo.get_version())) then
+                       return false
+               end
+
+               # check compat os
+               @pkginfo.get_target_packages(@os).each do |p|
+                       if not p.os_list.include?(o.os) then return false end
+               end
+
+               return true
+       end
+
+
+       def has_build_dependency?(other_job)
+
+               if has_same_packages?(other_job) or
+                       does_depend_on?(other_job) or
+                       does_depended_by?(other_job) then
+
+                       return true
+               else
+                       return false
+               end
+       end
+
+
        def has_same_packages?( wjob )
-               for pkg in @pkginfo.packages
-                       for wpkg in wjob.pkginfo.packages
+
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               # same package must have same os
+               if not @os.eql? wjob.os then
+                       return false
+               end
+
+               # check package name
+               get_packages().each do |pkg|
+                       wjob.get_packages().each do |wpkg|
                                if pkg.package_name == wpkg.package_name then
                                        #puts "Removed from candiated... A == B"
                                        return true
                                end
                        end
                end
+
                return false
        end
 
 
        def does_depend_on?( wjob )
-               for dep in @pkginfo.get_build_dependencies(@os, BuildServer::HOST_OS)
-                       for wpkg in wjob.pkginfo.packages
-                               if dep.package_name == wpkg.package_name then
+
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               # compare build dependency
+               get_build_dependencies(@os).each do |dep|
+                       wjob.get_packages().each do |wpkg|
+                               # dep packages of my job must have same name and target os
+                               #  with packages in working job
+                               if dep.package_name == wpkg.package_name and
+                                       dep.target_os_list.include? wjob.os then
                                        #puts "Removed from candiated... A -> B"
                                        return true
                                end
                        end
                end
+
                return false
        end
 
 
        def does_depended_by?( wjob )
-               for pkg in @pkginfo.packages
-                       for dep in wjob.pkginfo.get_build_dependencies(@os, BuildServer::HOST_OS)
-                               if pkg.package_name == dep.package_name then
+
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               get_packages().each do |pkg|
+                       wjob.get_build_dependencies(wjob.os).each do |dep|
+                               # dep package of working job must have same name and target os
+                               #  with packages in my job
+                               if dep.package_name == pkg.package_name and
+                                       dep.target_os_list.include? @os then
                                        #puts "Checking... A <- B"
                                        return true
                                end
@@ -128,89 +399,203 @@ class BuildJob
 
 
        def is_connected?
+               return @log.is_connected?
+       end
+
 
-               # nil? then false
-               if @outstream.nil? then
+       # return the job is asyncronous job
+       def is_asynchronous_job?
+               if not @log.has_second_out? then
+                       return true
+               else
                        return false
                end
+       end
 
-               # send chk signal
-               begin
-                       BuildCommServer.send_chk( @outstream )
-               rescue
-                       return false
+
+       # remove job from reverse success job
+       def remove_rev_success_job( job )
+               @rev_success_jobs.delete job if @rev_success_jobs.include? job
+       end
+
+
+       # check [project,os] is in reverse fail project list
+       def is_rev_fail_project( prj, os )
+               # check the project already exist
+               @rev_fail_projects.each do |p|
+                       if p[0] == prj and p[1] == os then
+                               return true
+                       end
                end
 
-               return true
+               return false
        end
 
 
-       # return the job is asyncronous job
-       def is_asynchronous_job?
-               if @outstream.nil? then
-                       return true
+       # add [project,os] to reverse fail project list
+       def add_rev_fail_project( prj, os )
+               # check the project already exist
+               @rev_fail_projects.each do |p|
+                       if p[0] == prj and p[1] == os then
+                               return
+                       end
+               end
+               # if not, add it
+               @rev_fail_projects.push [prj,os]
+       end
+
+
+       # remove [project,os] from reverse fail project list
+       def remove_rev_fail_project( prj, os )
+               remove_list = []
+
+               # check project and os name
+               @rev_fail_projects.each do |p|
+                       if p[0] == prj and p[1] == os then
+                               remove_list.push p
+                       end
+               end
+
+               # remove
+               remove_list.each do |r|
+                       @rev_fail_projects.delete r
+               end
+       end
+
+
+       # get project that my job is dependent on
+       def get_build_dependent_projects()
+               if @build_dep_prjs.nil? then
+                       deps = @pkginfo.get_build_dependencies(@os)
+                       pkgs = deps.map do |x|
+                               # if "os" is not specified, use my "os"
+                               if x.target_os_list.nil? or x.target_os_list.empty? then
+                                       os = @os
+                               else
+                                       os = x.target_os_list[0]
+                               end
+
+                               # package as item
+                               @pkgsvr_client.get_pkg_from_list(x.package_name, os)
+                       end
+                       prjs = @server.prjmgr.get_projects_from_pkgs(pkgs, get_distribution_name())
+                       @build_dep_prjs = prjs
+               end
+
+               return @build_dep_prjs
+       end
+
+
+       # check if the project is my dependent project
+       def is_build_dependent_project( prj, os )
+               dep_list = get_build_dependent_projects()
+               dep_list.each do |dep|
+                       if dep[0] == prj and dep[1] == os then
+                               return true
+                       end
+               end
+
+               return false
+       end
+
+
+       def progress
+               return ""
+       end
+
+
+       def get_log_url()
+               # only when server support log url
+               if @server.job_log_url.empty? then
+                       return "",""
+               end
+
+               url = "#{@server.job_log_url}/#{@id}/log"
+               # if remote, the file existence must be checked
+               if File.exist? "#{@job_root}/remote_log" then
+                       return url,"#{@server.job_log_url}/#{@id}/remote_log"
                else
-                       return false
+                       return url,""
                end
        end
+
+
        #
        # PROTECTED METHODS
        #
-       protected
 
 
-       # main module   
-       def thread_main
+       # main module
+       protected
+       def job_main()
+               @log.info( "Invoking a thread for building Job #{@id}", Log::LV_USER)
+               if @status == "ERROR" then return end
                @log.info( "New Job #{@id} is started", Log::LV_USER)
-               
-               @status = "BUILDING"
-
-               # update local package server
-               @server.local_pkgsvr.sync( @server.local_pkgsvr.get_default_dist_name(), false )
-
-               # checking version
-               if not check_package_version()
-                       @status = "ERROR"
-
-                       return
-               end
 
                # checking build dependency
-               if not check_build_dependency()
+               if not @is_remote_job and not @is_internal_job and
+                       not check_build_dependency() then
+                       if @is_internal_job then copy_result_files_to_master() end
                        @status = "ERROR"
-                       return
+                       return false
                end
 
                # clean build
-               if not build()
+               if not build() then
+                       if @is_internal_job then copy_result_files_to_master() end
+
                        @status = "ERROR"
-                       return
+                       return false
                end
 
                # upload
-               if not upload()
+               if not @is_rev_build_check_job and not @is_internal_job and
+                       @parent.nil? and
+                       not upload() then
                        @status = "ERROR"
-                       return
+                       return false
                end
-               
+
+               # copy result files to transport path
+               if @is_internal_job then
+                       copy_result_files_to_master()
+               elsif not @parent.nil? and not @is_rev_build_check_job then
+                       copy_result_files(@parent.source_path)
+               end
+
                # INFO. don't change this string
                @log.info( "Job is completed!", Log::LV_USER)
                @status = "FINISHED"
+               return true
        end
 
 
        # check if local package version is greater than server
-       def     check_package_version()
+       def     check_package_version( source_info )
                @log.info( "Checking package version ...", Log::LV_USER)
 
-               # package update
-               @pkgsvr_client.update
+               # check if version is same and source_info is different
+               ver_local = @pkginfo.packages[0].version
+               old_source_info = @project.get_source_info( ver_local )
+               if not old_source_info.nil? and old_source_info != source_info then
+                       @log.error( "Source code has been changed without increasing version!", Log::LV_USER)
+                       @log.error( " * Version : #{ver_local}", Log::LV_USER)
+                       @log.error( " * Before  : #{old_source_info}", Log::LV_USER)
+                       @log.error( " * Current : #{source_info}", Log::LV_USER)
 
-               for pkg in @pkginfo.packages
-                       ver_local = pkg.version
-                       #ver_svr = @pkgsvr_client.get_package_version( pkg.package_name, @os )
-            ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version")
-                       if not ver_svr.nil? and Version.new(ver_local) <= Version.new(ver_svr) then
+                       return false
+               end
+
+               # compare with package version in package server
+               @pkginfo.packages.each do |pkg|
+                       # check all supported os
+                       ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version")
+                       # ignore if package does not exist
+                       if ver_svr.nil? then next end
+
+                       # compare version
+                       if Version.new(ver_local) < Version.new(ver_svr) or
+                               ( not @force_rebuild and Version.new(ver_local) == Version.new(ver_svr) )  then
                                @log.error( "Version must be increased : #{ver_local} <= #{ver_svr}", Log::LV_USER)
                                return false
                        end
@@ -221,193 +606,592 @@ class BuildJob
 
 
        # build dependency version
+       # make sure that package server has all dependency packages of job
        def check_build_dependency()
                @log.info( "Checking build dependency ...", Log::LV_USER)
+               @pkgsvr_client.update
+               unmet_bdeps = []
+               @pkginfo.get_build_dependencies( @os ).each do |dep|
+                       # if parent exist, search parent source path first
+                       # if not found, check package server
+                       ver_svr = nil
+                       if not @parent.nil? then
+                               local_pkg = get_local_path_of_dependency( dep, @parent )
+                               if not local_pkg.nil? then
+                                       ver_svr = Utils.get_version_from_package_file( local_pkg )
+                               else
+                                       ver_svr = nil
+                               end
+                       end
+                       if not ver_svr.nil? then next end
+
+                       if not remote_package_of_dependency_exist?(dep) then
+                               unmet_bdeps.push dep
+                       end
+               end
+
+               @log.info( "Checking install dependency ...", Log::LV_USER)
+               unmet_ideps = []
+               @pkginfo.get_install_dependencies( @os ).each do |dep|
+                       # if parent exist, search pkginfos for all sub jobs
+                       # if not found, check package server
+                       found = false
+                       if not @parent.nil? and @parent.type == "MULTIBUILD" then
+                               @parent.get_sub_jobs().each do  |j|
+                                       os = (dep.target_os_list.empty?) ? @os : dep.target_os_list[0]
+                                       if j.pkginfo.pkg_exist?(dep.package_name, dep.base_version, os) then
+                                               found = true; break
+                                       end
+                               end
+                       end
+                       if found then next end
+
+                       if not remote_package_of_dependency_exist?(dep) then
+                               unmet_ideps.push dep
+                       end
+               end
+
+               # unmet dependencies found , report the errors
+               if not unmet_bdeps.empty? or not unmet_ideps.empty? then
+                       @log.error( "Unmet dependency found!", Log::LV_USER)
+                       unmet_bdeps.each do  |d|
+                               os = (d.target_os_list.empty?) ? @os : d.target_os_list[0]
+                               @log.error( " * #{d.package_name}(#{os}) for build-dependency", Log::LV_USER)
+                       end
+                       unmet_ideps.each do  |d|
+                               os = (d.target_os_list.empty?) ? @os : d.target_os_list[0]
+                               @log.error( " * #{d.package_name}(#{os}) for install-dependency", Log::LV_USER)
+                       end
+
+                       return false
+               else
+                       return true
+               end
+       end
+
+
+       # build clean
+       def     build()
 
-               for dep in @pkginfo.get_build_dependencies( @os, @host_os )
-                       #ver_svr = @pkgsvr_client.get_package_version( dep.package_name, @os )
-                       if dep.target_os_list.count != 0 then
-                               dep_target_os = dep.target_os_list[0]
+               # check there are pending packages which wait for me
+               # it will return nil if not exist
+               # this process must be skip if it is sub-job
+               if not @is_rev_build_check_job and not @is_internal_job then
+                       @server.cancel_lock.synchronize do
+                               @pending_ancestor = get_pending_ancestor_job()
+                       end
+               end
+
+               if not @pending_ancestor.nil? then
+                       # resolve other pending job
+                       resolve()
+               elsif @resolve then
+                       # wait for being resolved by other jobs
+                       # this condition must be placed after checking pending status
+                       wait_resolve()
+               else
+                       # build
+                       build_normal()
+               end
+       end
+
+
+       # return pending job that wait for me
+       def get_pending_ancestor_job()
+               @server.jobmgr.get_pending_jobs.each do |job|
+                       # must have same distribution
+                       if get_distribution_name() != job.get_distribution_name() then
+                               next
+                       end
+
+                       if job.is_rev_fail_project(@project,@os) then
+                               return job
+                       end
+               end
+
+               return nil
+       end
+
+
+       # check whether build this job or not
+       # if not build, then return its compat pkgs list
+       def check_compatable_packages
+               compat_pkgs = [] # [ package name, os, local_path ]
+
+               @pkginfo.get_target_packages(@os).each do |p|
+                       # if package has only os then must build
+                       if p.os_list.count <= 1 then return [] end
+
+                       compat_found = false
+                       p.os_list.each do |o|
+                               # check parent pkgs first
+                               if not @parent.nil? then
+                                       parent_pkgs = Dir.glob("#{@parent.source_path}/#{p.package_name}_*_*.zip")
+                                       parent_pkgs.each do |lp|
+                                               lpname = Utils.get_package_name_from_package_file( lp )
+                                               lver = Utils.get_version_from_package_file(lp)
+                                               los = Utils.get_os_from_package_file( lp )
+                                               if lpname == p.package_name and o == los and lver == p.version then
+                                                       compat_pkgs.push [p.package_name,o,lp]
+                                                       compat_found = true
+                                                       break
+                                               end
+                                       end
+                               end
+                               if compat_found then break end
+
+                               # check other package already in package server
+                               ver_svr = @pkgsvr_client.get_attr_from_pkg( p.package_name, o, "version")
+                               if not ver_svr.nil? and p.version.eql? ver_svr then
+                                       compat_pkgs.push [p.package_name,o,nil]
+                                       compat_found = true
+                                       break
+                               end
+                       end
+
+                       # if there is no compat pkgs for one pkg, then must build
+                       if not compat_found then return [] end
+               end
+
+               return compat_pkgs
+       end
+
+
+       def     build_normal()
+               @log.info( "Started to build this job...", Log::LV_USER)
+
+               # create builder
+               if @is_remote_job then
+                       builder = RemoteBuilder.new("JB#{@id}", @remote_server, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd)
+                       @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+                       @log.info( " - Remote Server : #{@remote_server.ip}:#{@remote_server.port}" )
+                       if not @server.ftp_addr.nil? then
+                               @log.info( " - FTP Server : #{@server.ftp_addr}" )
+                       end
+               else
+                       builder = Builder.create( "JB#{@id}", @pkgsvr_url, nil,
+                                                                        "#{@buildroot_dir}", @server.build_cache_dir )
+                       if builder.nil?
+                               @log.error( "Creating job builder failed", Log::LV_USER)
+                               return false
+                       end
+                       @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+                       @log.info( " - Package Server : #{@pkgsvr_url}" )
+                       @log.info( " - Build Cache Path : #{@server.build_cache_dir}" )
+               end
+               @log.info( " - Log Path : #{@log.path}" )
+
+               # if sub job, install dependent packages of parent-pkgs and not clean
+               use_clean = true
+               local_pkgs = []
+               local_pkgs += @external_pkgs
+               if not @parent.nil? then
+                       use_clean = false
+                       # get local packages to install
+                       deps = @pkginfo.get_build_dependencies(@os)
+                       local_pkgs += get_local_paths_of_chained_dependencies( deps, @parent )
+               end
+               local_pkgs.uniq!
+
+               #compatable os support
+               compat_ok = true
+               compat_pkgs = check_compatable_packages
+               if compat_pkgs.size > 0 and not @is_rev_build_check_job then
+                       # bring package from server for reverse check
+                       compat_pkgs.each do |p|
+                               pkg_name = p[0]; cos = p[1]; local_path = p[2]
+
+                               if not local_path.nil? then
+                                       ext = File.extname(local_path)
+                                       base_package_name= File.basename(local_path, "#{cos}#{ext}")
+                                       @log.info( "Copying compatible package:#{local_path}", Log::LV_USER)
+                                       @log.info( "Creating package file ... #{base_package_name}#{@os}#{ext}", Log::LV_USER)
+                                       FileUtils.cp local_path, "#{@source_path}/#{base_package_name}#{@os}#{ext}"
+                               else
+                                       @log.info( "Downloading compatible package:#{pkg_name}(#{cos})", Log::LV_USER)
+                                       loc = @pkgsvr_client.download(pkg_name, cos, false)
+                                       if loc.nil? or loc.count != 1 then
+                                               @log.warn( "Downloading compatible package failed!:#{pkg_name}(#{cos})", Log::LV_USER)
+                                               compat_ok = false
+                                               break
+                                       end
+                                       ext = File.extname(loc[0])
+                                       base_package_name= File.basename(loc[0], "#{cos}#{ext}")
+                                       @log.info( "Creating package file ... #{base_package_name}#{@os}#{ext}", Log::LV_USER)
+                                       FileUtils.mv loc[0], "#{@source_path}/#{base_package_name}#{@os}#{ext}"
+                               end
+                       end
+               else
+                       compat_ok = false
+               end
+
+               # if compat check failed
+               if not compat_ok then
+                       # build
+                       if @is_remote_job then
+                               result = builder.build_job(self, local_pkgs)
                        else
-                               dep_target_os = @os
+                               result =  builder.build_job(self, use_clean, local_pkgs, false )
                        end
-                       ver_svr = @pkgsvr_client.get_attr_from_pkg( dep.package_name, dep_target_os, "version")
+                       if not result then
+                               @log.error( "Building job failed", Log::LV_USER)
+                               write_log_url()
+                               return false
+                       end
+               end
 
-                       if ver_svr.nil?
-                               @log.error( "The package \"#{dep.package_name}\" for build-dependency is not found}", Log::LV_USER)
+               # check reverse dependecy if not sub jobs
+
+               if not @no_reverse then
+                       if not @is_rev_build_check_job and not @is_internal_job and
+                               not ReverseBuildChecker.check( self, true ).empty? then
+                               @log.error( "Reverse-build-check failed!" )
                                return false
                        end
+               end
+
+               return true
+       end
+
 
-                       if not dep.match? ver_svr
-                               @log.error( "Version for build-dependency in not matched : server version => #{ver_svr}", Log::LV_USER)
+       # wait to be resolved by other jobs
+       def wait_resolve()
+               @log.info( "Started to build this job and wait for being resolved...", Log::LV_USER)
+
+               # create builder
+               if @is_remote_job then
+                       builder = RemoteBuilder.new("JB#{@id}", @remote_server, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd)
+                       @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+                       @log.info( " - Remote Server : #{@remote_server.ip}:#{@remote_server.port}" )
+                       if not @server.ftp_addr.nil? then
+                               @log.info( " - FTP Server : #{@server.ftp_addr}" )
+                       end
+               else
+                       builder = Builder.create( "JB#{@id}", @pkgsvr_url, nil,
+                                                                        "#{@buildroot_dir}/#{@os}", @server.build_cache_dir )
+                       if builder.nil?
+                               @log.error( "Creating job builder failed", Log::LV_USER)
                                return false
                        end
-               end     
-               
+                       @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+                       @log.info( " - Package Server : #{@pkgsvr_url}" )
+                       @log.info( " - Build Cache Path : #{@server.build_cache_dir}" )
+               end
+               @log.info( " - Log Path : #{@log.path}" )
+
+               # build
+               if @is_remote_job then
+                       result = builder.build_job(self, [])
+               else
+                       result =  builder.build_job(self, true, [], false )
+               end
+               if not result then
+                       @log.error( "Building job failed", Log::LV_USER)
+                       write_log_url()
+                       return false
+               end
+
+               # check reverse dependecy
+               @rev_fail_projects = ReverseBuildChecker.check(self, false)
+               if @rev_fail_projects.empty? then
+                       # if no problem?, it OK
+                       return true
+               end
+
+               # pending
+               @status = "PENDING"
+               @log.info( "Entered the PENDING state ...", Log::LV_USER)
+               old_msg = ""
+               while @status == "PENDING"
+                       new_msg = @rev_fail_projects.map {|p| "#{p[0].name}(#{p[1]})"}.join(", ")
+                       if old_msg != new_msg then
+                               @log.error( " * Waiting for building next projects: #{new_msg}", Log::LV_USER)
+                               old_msg = new_msg
+                       end
+                       sleep 1
+               end
+
                return true
        end
 
 
-       # build clean
-       def     build()
-        if @resolve then 
-                       @log.info( "Resolving job...", Log::LV_USER)
+       # resolve other pending job
+       def     resolve()
+
+               # wait for other build-dependent projects are resolved
+               old_msg = ""
+               wait_prjs = @pending_ancestor.rev_fail_projects.select {|p| is_build_dependent_project(p[0], p[1])}
+               @log.info("Checking build dependency before RESOLVE", Log::LV_USER)
+               while not wait_prjs.empty?
+                       @status = "PENDING"
+                       new_msg = wait_prjs.map {|p| "#{p[0].name}(#{p[1]})"}.join(", ")
+                       if new_msg != old_msg then
+                               @log.info(" * Waiting for building next projects: #{new_msg}", Log::LV_USER)
+                               old_msg = new_msg
+                       end
+                       sleep 1
+                       wait_prjs = @pending_ancestor.rev_fail_projects.select {|p| is_build_dependent_project(p[0], p[1])}
+               end
+
+               # return back to "WORKING"
+               @status = "WORKING"
+
+               @log.info( "Started to build this job and resolve other pending job...", Log::LV_USER)
+
+               # create builder
+               if @is_remote_job then
+                       builder = RemoteBuilder.new("JB#{@id}", @remote_server, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd)
+                       @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+                       @log.info( " - Remote Server : #{@remote_server.ip}:#{@remote_server.port}" )
+                       if not @server.ftp_addr.nil? then
+                               @log.info( " - FTP Server : #{@server.ftp_addr}" )
+                       end
                else
-                       @log.info( "Building job...", Log::LV_USER)
-               end 
+                       builder = Builder.create( "JB#{@id}", @pkgsvr_url, nil,
+                                                                        "#{@buildroot_dir}/#{@os}", @server.build_cache_dir )
+                       if builder.nil?
+                               @log.error( "Creating job builder failed", Log::LV_USER)
+                               return false
+                       end
+                       @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
+                       @log.info( " - Package Server : #{@pkgsvr_url}" )
+                       @log.info( " - Build Cache Path : #{@server.build_cache_dir}" )
+               end
+               @log.info( " - Log Path : #{@log.path}" )
+
+               # get local packages to overwite
+               # they must be composed of packages of pending jobs and its success list
+               local_pkgs=[]
+               local_pkgs += @external_pkgs
+               src_path = @pending_ancestor.source_path
+               ver = @pending_ancestor.pkginfo.get_version()
+               @pending_ancestor.pkginfo.get_target_packages(@os).each do |pkg|
+                       local_pkgs.push "#{src_path}/#{pkg.package_name}_#{ver}_#{@os}.zip"
+               end
+               @pending_ancestor.rev_success_jobs.each do |job|
+                       src_path = job.source_path
+                       ver = job.pkginfo.get_version()
+                       job.pkginfo.get_target_packages(@os).each do |pkg|
+                               local_pkgs.push "#{src_path}/#{pkg.package_name}_#{ver}_#{@os}.zip"
+                       end
+               end
 
-               # create builder 
-               builder = Builder.create( "JB#{@id}", @pkgserver_url,@log.path )
-               if builder.nil?
-                       @log.error( "Creating job builder failed", Log::LV_USER)
+               # build
+               if @is_remote_job then
+                       result = builder.build_job(self, local_pkgs)
+               else
+                       result = builder.build_job(self, true, local_pkgs, false )
+               end
+               if not result then
+                       @log.error( "Building job failed", Log::LV_USER)
+                       write_log_url()
                        return false
                end
-               @log.info( "JobBuilder##{@id} is created", Log::LV_USER)
-               
-               # set log output
-               builder.log.close
-               builder.log = @log
-
-        #make pending_pkg_dir_list
-        pending_pkg_dir_list = []
-        ignore_rev_dep_build_list = []
-        @pkginfo.packages.each do |i|
-            @server.pending_jobs.each do |pj|
-                if pj.rev_fail_list.include? i.package_name then 
-                    pending_pkg_dir_list.push pj.source_path
-                    pending_pkg_dir_list += pj.rev_success_list.map {|pjs| pjs.source_path}
-                    ignore_rev_dep_build_list = pj.rev_fail_list
-                    break
-                end 
-            end 
-            if not pending_pkg_dir_list.empty? then break end 
-        end 
-        dependency_package_exist = (not pending_pkg_dir_list.empty?)
-
-               # build 
-        if @resolve then  
-            @rev_fail_list = builder.build_resolve(@source_path, @os, [], []) 
-
-            # clean build failed
-            if @rev_fail_list.nil? then 
-                @log.error( "Resolve building job failed", Log::LV_USER)
-                return false
-            end
-
-            # pending 
-            @status = "PENDING"
-
-            # rev build successed
-            if @rev_fail_list.empty? then 
-                @rev_success_list.each do |s|
-                    s.status = ""
-                end 
-                @status = ""
-            end
-
-            while @status == "PENDING" 
-                sleep 1
-            end 
-            return true
-        else
-            if not builder.build(@source_path, @os, true, true, pending_pkg_dir_list, ignore_rev_dep_build_list )
-                @log.error( "Building job failed", Log::LV_USER)
-                return false
-            end
-
-            if dependency_package_exist then 
-                @server.pending_jobs.each do |j| 
-                    if j.source_path == pending_pkg_dir_list[0] then 
-                        j.rev_fail_list -= @pkginfo.packages.map{|p| p.package_name}
-                        j.rev_success_list.push self
-                        if j.rev_fail_list.empty? then 
-                            j.rev_success_list.each do |s|
-                                s.status = ""
-                            end 
-                            j.status = ""
-                        else
-                            @status = "PENDING"
-                            while @status == "PENDING" 
-                                sleep 1
-                            end 
-                        end 
-                        break
-                    end 
-                end 
-            end 
-        end
-
-               # remove builder
-               Builder.remove( "builder_#{@id}" )
-               
+
+               # check reverse dependecy and update parent rev_fail_project list
+               new_fail_projects = ReverseBuildChecker.check(self, false)
+               new_fail_projects.each do |p|
+                       @pending_ancestor.add_rev_fail_project(p[0], p[1])
+               end
+
+               # update the status of pending job
+               @status = "PENDING"
+               @pending_ancestor.remove_rev_fail_project(@project, @os)
+               @pending_ancestor.rev_success_jobs.push self
+               if @pending_ancestor.rev_fail_projects.empty? then
+                       @pending_ancestor.status = "RESOLVED"
+                       @pending_ancestor.rev_success_jobs.each do |job|
+                               job.status = "RESOLVED"
+                       end
+               else
+                       @log.info( "Entered the PENDING state ...", Log::LV_USER)
+                       old_msg = ""
+                       while @status == "PENDING"
+                               new_msg = @pending_ancestor.rev_fail_projects.map {|p| "#{p[0].name}(#{p[1]})"}.join(", ")
+
+                               if new_msg != old_msg then
+                                       @log.info(" * Waiting for building next projects: #{new_msg}", Log::LV_USER)
+                                       old_msg = new_msg
+                               end
+
+                               sleep 1
+                       end
+               end
+
                return true
        end
 
 
        def upload()
                @log.info( "Uploading ...", Log::LV_USER)
-       
+
                # get package path list
                binpkg_path_list = Dir.glob("#{@source_path}/*_*_#{@os}.zip")
-               srcpkg_path_list = Dir.glob("#{@source_path}/*.tar.gz")
 
                # upload
-               u_client = Client.new( @server.pkgserver_url, nil, @log )
-               u_client.update
-               snapshot = u_client.upload( @server.pkgserver_addr, 
-                       @server.pkgserver_id, binpkg_path_list, srcpkg_path_list, true)
+               u_client = Client.new( @pkgsvr_url, nil, @log )
+               snapshot = u_client.upload( @pkgsvr_ip, @pkgsvr_port, binpkg_path_list, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd)
 
                if snapshot.nil? then
                        @log.info( "Upload failed...", Log::LV_USER)
 
                        return false
                end
-       
+
                # update local
                @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER)
                @pkgsvr_client.update
-               @server.local_pkgsvr.sync( @server.local_pkgsvr.get_default_dist_name(), false )
                @log.info("Snapshot: #{snapshot}", Log::LV_USER)
-       
+
                return true
        end
 
 
-       # remote main module    
-       def remote_thread_main(server)
-               @log.info( "Job #{@id} is requested to be built on remote server ", Log::LV_USER)
-               
-               @status = "REMOTE_BUILDING"
+       def copy_result_files(dst_path)
+               @log.info( "Copying result files to #{dst_path}", Log::LV_USER)
 
-               # open
-               client = BuildCommClient.create( server.remote_ip, server.port )
-               if client.nil? then
-                       @status = "ERROR"
-                       return
-               end
-               
-               # send & receive
-               if client.send("BUILD,GIT,#{@git_repos},#{@git_commit},#{@os},,NO") then
-                       result = client.read_lines do |l|
-                               if l.include? "Job is stopped by ERROR" then
-                                       @status = "ERROR"
-                               end
-                               # ddd list
-                               @log.output( l.strip, Log::LV_USER)
+               # get package path list
+               binpkg_path_list = Dir.glob("#{@source_path}/*_*_#{@os}.zip")
+
+               binpkg_path_list.each do |file|
+                       @log.info( " * #{file}", Log::LV_USER)
+                       FileUtils.cp(file,"#{dst_path}/")
+               end
+
+               return true
+       end
+
+
+       # copy binary package files and log file to transport dir
+       def copy_result_files_to_master()
+               outgoing_dir = "#{@server.transport_path}/#{@dock_num}"
+
+               @log.info( "Copying log to #{outgoing_dir}", Log::LV_USER)
+               file = "#{@source_path}/../log"
+               FileUtils.copy_file(file, "#{outgoing_dir}/remote_log")
+
+               # copy result files, if not reverse build
+               if not @is_rev_build_check_job then
+                       return copy_result_files( outgoing_dir )
+               else
+                       return true
+               end
+       end
+
+
+       protected
+       def get_local_path_of_dependency( dep, parent )
+               dep_target_os = get_os_of_dependency(dep)
+
+               # search my parent job and its parent job
+               binpkgs = Dir.glob("#{parent.source_path}/#{dep.package_name}_*_#{dep_target_os}.zip")
+               if binpkgs.count == 0 and not parent.get_parent_job().nil? then
+                       binpkgs = Dir.glob("#{parent.get_parent_job().source_path}/#{dep.package_name}_*_#{dep_target_os}.zip")
+               end
+
+               if binpkgs.count > 0 then
+                       pkg = binpkgs[0]
+                       version = Utils.get_version_from_package_file(pkg)
+                       if dep.match? version then
+                               return pkg
+                       else
+                               return nil
                        end
-                       if not result then @status = "ERROR" end
+               else
+                       return nil
                end
+       end
 
-               # close socket
-               client.terminate
 
-               # INFO. don't change this string
-               if @status != "ERROR" then
-                       @log.info( "Job is just finished", Log::LV_USER)
-                       @status = "FINISHED"
+       protected
+       def get_local_paths_of_chained_dependencies( deps, parent )
+               pkg_paths = []
+
+               # get packages names that is related my build dependency
+               chained_deps = get_local_chained_dependencies( deps, parent )
+
+               # get all local path of dependencies
+               chained_deps.each do  |dep|
+                       new_path = get_local_path_of_dependency(dep, parent)
+                       if not new_path.nil? then
+                               pkg_paths.push new_path
+                       end
                end
 
-               return  
+               # remove duplicates
+               pkg_paths.uniq!
+
+               return pkg_paths
+       end
+
+
+       protected
+       def get_local_chained_dependencies( deps, parent )
+
+               chained_deps = []
+               chained_deps += deps
+
+               # if parent is multi build job, gether all install dependency of dependency.
+               if parent.type == "MULTIBUILD" then
+                       begin
+                               old_deps_count = chained_deps.count
+                               new_deps = []
+                               chained_deps.each do  |dep|
+                                       dep_target_os = get_os_of_dependency(dep)
+
+                                       parent.get_sub_jobs().each do  |j|
+                                               new_deps += j.pkginfo.get_install_dependencies(dep_target_os, dep.package_name)
+                                       end
+                               end
+                               chained_deps += new_deps
+                               chained_deps.uniq! {|d| d.package_name }
+                       end while chained_deps.count != old_deps_count
+               end
+
+               # check parent of parent
+               if not parent.get_parent_job().nil? then
+                       chained_deps = get_local_chained_dependencies(chained_deps, parent.get_parent_job())
+               end
+
+               return chained_deps
+       end
+
+
+       protected
+       def remote_package_of_dependency_exist?(dep)
+               dep_target_os = get_os_of_dependency(dep)
+
+               # search
+               ver_svr = @pkgsvr_client.get_attr_from_pkg( dep.package_name, dep_target_os, "version")
+               if ver_svr.nil? then return false end
+               if not dep.match? ver_svr then return false end
+
+               return true
+       end
+
+
+       # write web url for log
+       protected
+       def write_log_url()
+               url,remote_url = get_log_url()
+               if not url.empty? then
+                       @log.info( " ** Log1: #{url}", Log::LV_USER)
+               end
+               if not remote_url.empty? then
+                       @log.info( " ** Log2: #{remote_url}", Log::LV_USER)
+               end
+       end
+
+
+       # get target os of dependency
+       protected
+       def get_os_of_dependency(dep)
+               # use the target os if not specified
+               if dep.target_os_list.count != 0 then
+                       dep_target_os = dep.target_os_list[0]
+               else
+                       dep_target_os = @os
+               end
        end
 
 end
index 7862f9836f38e64ce9ae8f2866941cfc9ff9a039..7328abef71c57ab0baf57bbfea502a0c03e9bb7c 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  BuildServer.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -26,154 +26,276 @@ Contributors:
 - S-Core Co., Ltd
 =end
 
+require 'rubygems'
 require 'fileutils'
+require 'dbi'
+require 'thread'
 $LOAD_PATH.unshift File.dirname(__FILE__)
-$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/pkg_server"
 require "SocketJobRequestListener.rb"
-require "RemoteBuildJob.rb"
-require "LocalBuildJob.rb"
-require "packageServer.rb"
+require "JobManager.rb"
+require "JobClean.rb"
+require "RemoteBuildServer.rb"
+require "PackageSync.rb"
+require "ProjectManager.rb"
+require "DistributionManager.rb"
 
 class BuildServer
-       attr_accessor :id, :path, :pkgserver_url, :pkgserver_addr, :pkgserver_id, :remote_ip, :port, :status, :friend_servers, :host_os, :log
-       attr_accessor :max_working_jobs, :working_jobs, :waiting_jobs, :remote_jobs, :pending_jobs
+       attr_accessor :id, :path, :status, :host_os, :log
+       attr_accessor :remote_servers
        attr_accessor :git_server_url, :git_bin_path
-       attr_accessor :job_log_url
-       attr_accessor :job_index
        attr_accessor :allowed_git_branch
-       attr_accessor :pkgsvr_cache_path, :local_pkgsvr
-
+       attr_accessor :jobmgr
+       attr_accessor :test_time
+       attr_accessor :password
+       attr_accessor :finish
+       attr_accessor :build_cache_dir
+       attr_accessor :ftp_addr
+       attr_accessor :ftp_port
+       attr_accessor :ftp_username
+       attr_accessor :ftp_passwd
+       attr_accessor :cleaner
+       attr_accessor :prjmgr, :distmgr
+       attr_accessor :transport_path
+       attr_accessor :cancel_lock
+       attr_accessor :upgrade
+       attr_accessor :db
+       attr_accessor :db_dsn, :db_user, :db_passwd, :db_version
        CONFIG_ROOT = "#{Utils::HOME}/.build_tools/build_server"
        HOST_OS = Utils::HOST_OS
 
        # initialize
-       def initialize (id, path, pkgserver_url, pkgserver_addr, pkgserver_id)
+       def initialize (id, path, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd)
                @id = id
                @path = path
-               @pkgserver_url = pkgserver_url
-               @pkgserver_addr = pkgserver_addr
-               @pkgserver_id = pkgserver_id
-               @friend_servers = []
-               @waiting_jobs = []
-               @working_jobs = []
-               @pending_jobs = []
-               @remote_jobs = []
-               @max_working_jobs=2
+               @remote_servers = []
                @req_listener = []
                @finish = false
-               # for friend server
-               @remote_ip = nil
-               # port number
-               @port = 2222
                # status
                @status = "RUNNING"
                # host_os
                @host_os = HOST_OS
                # log
-               @log = nil
+               @log =nil
                @git_server_url = "gerrithost"
                @git_bin_path = "/usr/bin/git"
-               @job_index = 0
-               @job_log_url = ""
                @allowed_git_branch = ""
                # local package server
                @pkgsvr_cache_path = nil
-               @local_pkgsvr = nil
+               # Job Manager
+               @jobmgr = JobManager.new(self)
+               @test_time=0 #test time in mili-seconds
+               @password="0000"
+               @ftp_addr = ftpsvr_addr
+               @ftp_port = ftpsvr_port
+               @ftp_username = ftpsvr_username
+               @ftp_passwd = ftpsvr_passwd
+               @cleaner=nil
+               @prjmgr = ProjectManager.new(self)
+               @distmgr = DistributionManager.new(self)
+               #
+               @transport_path = "#{@path}/transport"
+               @cancel_lock = Mutex.new
+
+               @upgrade = false
+
+               #DB settring
+               @db = nil
+               @db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{@id}/server.db"
+               @db_user = nil
+               @db_passwd = nil
+               @db_version = 1
+               @sqlite3_db_mutex = Mutex.new
+
+               #DB upgrade SQL command
+               @db_migrate = []
+               #@db_migrate[0]= ["CREATE TABLE test(value INTEGER)", "INSERT INTO test (value) VALUES('3')"]
+       end
+
+       def send_mail
+               result = nil
+               get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'send_mail'")[0]
+               end
+               return (result.nil?) ? "NO" : result
+       end
+
+       def send_mail=(mail)
+               get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{mail}' WHERE property = 'send_mail'"
+               end
+       end
+
+       def keep_time
+               result = nil
+               get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'keep_time'")[0]
+               end
+               return (result.nil?) ? 86400 : result.to_i
+       end
+
+       def keep_time=(second)
+               get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{second}' WHERE property = 'keep_time'"
+               end
        end
 
+       def pkg_sync_period
+               result = nil
+               get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'pkg_sync_period'")[0]
+               end
+               return (result.nil?) ? 600 : result.to_i
+       end
 
+       def pkg_sync_period=(second)
+               get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{second}' WHERE property = 'pkg_sync_period'"
+               end
+       end
+
+       def changelog_check
+               result = nil
+               get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'changelog_check'")[0]
+               end
+               return (result.nil?) ? false : result =~ /true/i
+       end
+
+       def changelog_check=(check)
+               t = check =~ /true/i
+               get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{t.to_s}' WHERE property = 'changelog_check'"
+               end
+       end
+
+       def job_log_url
+               result = nil
+               get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'job_log_url'")[0]
+               end
+               return (result.nil?) ? "" : result
+       end
+
+       def job_log_url=(url)
+               get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{url}' WHERE property = 'job_log_url'"
+               end
+       end
+
+       def port
+               result = nil
+               get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'port'")[0]
+               end
+               return (result.nil?) ? "" : result
+       end
+
+       def port=(svr_port)
+               get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{svr_port}' WHERE property = 'port'"
+               end
+       end
+
+       def db_inc
+               return (@db_dsn =~ /^Mysql/i) ? "AUTO_INCREMENT" : "AUTOINCREMENT"
+       end
+
+       def db_post_fix
+               return (@db_dsn =~ /^Mysql/i) ? "ENGINE = INNODB DEFAULT CHARSET = UTF8" : ""
+       end
+
+       def db_now
+               return (@db_dsn =~ /^Mysql/i) ? "NOW()" : "datetime('now')"
+       end
        # start server daemon
        def start
-               # start logger
-               @log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{@id}/log" )
-
-               # set local package server for cache
-               @log.info "Setting local package server..."
-               pkgsvr_id = @id
-               pkgsvr_dist = @pkgserver_url.split("/")[-1]
-               @local_pkgsvr = PackageServer.new( pkgsvr_id )
-               if @local_pkgsvr.location.empty? then 
-                       FileUtils.mkdir_p @pkgsvr_cache_path
-                       @local_pkgsvr.create(pkgsvr_id, pkgsvr_dist, @pkgserver_url, @pkgsvr_cache_path )
-               else
-                       # check path is changed, recreate it
-                       if @local_pkgsvr.location != "#{@pkgsvr_cache_path}/#{pkgsvr_id}" then
-                               # remove
-                               @local_pkgsvr.remove_server( pkgsvr_id )
-                               # create
-                               FileUtils.mkdir_p @pkgsvr_cache_path
-                               @local_pkgsvr.create(pkgsvr_id, pkgsvr_dist, @pkgserver_url, @pkgsvr_cache_path )
-                       end
+               # set build cache dir
+               @build_cache_dir="#{BuildServer::CONFIG_ROOT}/#{@id}/build_cache"
+               if not File.exist? @build_cache_dir then
+                       FileUtils.mkdir_p @build_cache_dir
                end
 
+               # init transport path
+               if not File.exist? @transport_path then FileUtils.mkdir_p @transport_path end
+
+               # init project mgr
+               @log.info "Setting Project Manager..."
+               @prjmgr.load()
+
+               # init job mgr
+               @log.info "Intializing Job Manager..."
+               @jobmgr.init()
+
                # set job request listener
                @log.info "Setting listener..."
                listener2 = SocketJobRequestListener.new(self)
                listener2.start
                @req_listener.push listener2
-       
-               # main loop
-               @log.info "Entering main loop..."
-               while( not @finish )
-                       # handle jobs
-                       handle()
-                       sleep 1
-               end
-       end
 
+               # set job cleaner
+               @log.info "Setting Job Cleaner..."
+               @cleaner =  JobCleaner.new(self)
+               @cleaner.start
 
-       # stop sever daemon
-       def stop
-               @finish = true
-       end
+               # set package server synchrontizer
+               @log.info "Setting Package Server Synchronizer..."
+               @pkg_sync =  PackageServerSynchronizer.new(self)
+               @pkg_sync.start
 
+               # main loop
+               @log.info "Entering main loop..."
+               begin
+                       if @test_time > 0 then start_time = Time.now end
+                       while( not @finish )
+
+                               # update friend server status
+                               @remote_servers = get_remote_servers()
+                               @remote_servers.each do |server|
+                                       # update state
+                                       get_db_connection() do |db|
+                                               server.update_state(db)
+                                       end
+                               end
 
-       # add a normal job
-       def add_job ( new_job )
-               @log.info "Added new job \"#{new_job.id}\""
-
-               Thread.new {
-                       # pre-verifiy
-                       if not new_job.pre_verify or new_job.status == "ERROR" then
-                               new_job.status = "ERROR"
-                               @log.info "Adding the job \"#{new_job.id}\" is canceled"
-                               new_job.terminate()
-                               Thread.current.exit
-                       end
+                               # handle jobs
+                               @jobmgr.handle()
 
-                       # check availabiltiy
-                       if not check_job_availability( new_job ) then
-                               new_job.log.error( "No servers that are able to build your packages.", Log::LV_USER)
-                               new_job.status = "ERROR"
-                               @log.info "Adding the job \"#{new_job.id}\" is canceled"
-                               new_job.terminate()
-                               Thread.current.exit
+                               # sleep
+                               if @test_time > 0 then
+                                       curr_time = Time.now
+                                       if (curr_time - start_time).to_i > @test_time then
+                                               puts "Test time is elapsed!"
+                                               break
+                                       end
+                               else
+                                       sleep 1
+                               end
                        end
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       @log.error e.backtrace.inspect
+               end
 
-                       @waiting_jobs.push( new_job )
-                       new_job.status = "WAITING"
-                       @log.info "Checking the job \"#{new_job.id}\" was finished!"
-               }
-       end
-
-
-       # get job list
-       def get_job_list()
-               list = []
-               list = list + @working_jobs + @remote_jobs + @waiting_jobs
+               if(@upgrade)
+                       exit(99)
+               end
+               # TODO: something should be done for server down
 
-               return list
        end
 
 
-       # query job status
-       def get_job_status( job )
-               return job.status
+       # stop sever daemon
+       def stop
+               @finish = true
        end
 
 
        # check the job can be built on this server
        def can_build?(job)
+               # check max allowed jobs
+               if @jobmgr.max_working_jobs <= 0 then
+                       return false
+               end
 
                # check me
                if job.can_be_built_on? @host_os then
@@ -184,294 +306,176 @@ class BuildServer
        end
 
 
-       def get_new_job_id
-               # get new id
-               new_id = @job_index
-
-               # save it
-               server_dir = "#{BuildServer::CONFIG_ROOT}/#{@id}"
-               f = File.open( "#{server_dir}/latest_job", "w" )
-               f.puts "#{new_id}"
-               f.close
-
-               # increae job idex
-               @job_index = @job_index + 1
-
-               return new_id
+       def get_remote_servers()
+               get_db_connection() do |db|
+                       return RemoteBuildServer.load_all(db)
+               end
        end
 
 
        # add new remote friend server
-       def add_friend_server( ip, port )
-       
-               # if already exit, return false
-               for svr in @friend_servers
-                       if svr.remote_ip.eql? ip and svr.port == port then
-                               return false
-                       end     
-               end
-
-               # create new one, and add it into list
-               new_server = BuildServer.new( "#{ip}_#{port}", nil, nil, nil, nil )
-               new_server.remote_ip = ip
-               new_server.port = port
-               new_server.status = "UNDEFINED"
-               @friend_servers.push new_server
+       def add_remote_server( ip, port )
+
+               get_db_connection() do |db|
+                       rs = RemoteBuildServer.load(ip, port, db)
+                       if not rs.nil? then return false end
+                       RemoteBuildServer.new(ip, port, "").save(db)
+               end
 
                return true
        end
 
 
-       # query remote server info & update server state
-       def update_state
+       # remove remote friend server
+       def remove_remote_server( ip, port )
+               get_db_connection() do |db|
+                       rs = RemoteBuildServer.load(ip, port, db)
+                       if rs.nil? then return false end
+                       rs.unload(db)
+               end
 
-               # only friend server
-               if not @path.nil? then return end
+               return true
+       end
 
-               # send 
-               @status = "DISCONNECTED"
-               client = BuildCommClient.create( @remote_ip, @port )
-               if client.nil? then return end
-               if client.send("QUERY,SYSTEM") then
-                       result = client.read_lines do |l|
-                               tok = l.split(",").map { |x| x.strip }
-                               @host_os = tok[0]
-                               @max_working_jobs = tok[1].to_i
-                               @status = "RUNNING"
-                       end
-                       if not result then @status = "DISCONNECTED" end
-               end
-               client.terminate
-               if @status == "DISCONNECTED" then return end
-
-               # send  
-               @working_jobs = []
-               @waiting_jobs = []
-               client = BuildCommClient.create( @remote_ip, @port )
-               if client.nil? then return end
-               if client.send("QUERY,JOB") then
-                       result = client.read_lines do |l|
-                               tok = l.split(",").map { |x| x.strip }
-                               
-                               job_status = tok[0]
-                               job_id = tok[1]
-                               new_job = RemoteBuildJob.new(job_id)
-                               case job_status
-                               when "WAITING" 
-                                       @waiting_jobs.push new_job
-                               when "WORKING" 
-                                       @working_jobs.push new_job
-                               else
-                                       #puts "Uncontrolled status"
-                               end     
+
+       def get_sync_package_servers()
+               result = []
+               get_db_connection() do |db|
+                       rows = db.select_all("SELECT sync_pkg_servers.pkgsvr_url, distributions.name FROM sync_pkg_servers,distributions WHERE sync_pkg_servers.distribution_id = distributions.id")
+                       rows.each do |row|
+                               result.push [row['pkgsvr_url'], row['name']]
                        end
-                       if not result then @status = "DISCONNECTED" end
-               else
-                       @status = "DISCONNECTED"
                end
-               client.terminate
-       end
 
+               return result
+       end
 
-       private
 
-       def handle()
-               # update friend server status
-               for server in @friend_servers
-                       # update state
-                       server.update_state
+       # add new remote pkg server
+       def add_sync_package_server( url, dist )
+               get_db_connection() do |db|
+                       row = db.select_one("SELECT distributions.id FROM sync_pkg_servers,distributions WHERE sync_pkg_servers.pkgsvr_url='#{url}' and distributions.name='#{dist}' and sync_pkg_servers.distribution_id = distributions.id")
+                       if not row.nil? then return false end
+                       row = db.select_one("SELECT id FROM distributions WHERE name='#{dist}'")
+                       dist_id = row['id'];
+                       db.do "INSERT INTO sync_pkg_servers (pkgsvr_url,period,distribution_id) VALUES('#{url}','#{@pkg_sync_period}',#{dist_id})"
                end
 
-               # Move working -> finished
-               #) Move working -> pending
-               for job in @working_jobs
-                       if job.status == "ERROR"
-                               @log.info "Job \"#{job.id}\" is stopped by ERROR" 
-                               @working_jobs.delete job        
-                       elsif job.status == "FINISHED" 
-                               @working_jobs.delete job
-                       elsif job.status == "PENDING" 
-                               @working_jobs.delete job
-                               @pending_jobs.push job
-                       end
-               end
+               return true
+       end
 
-               # Move pending -> finished 
-               for job in @pending_jobs
-                       if job.status == "ERROR"
-                               @log.info "Job \"#{job.id}\" is stopped by ERROR" 
-                               @pending_jobs.delete job        
-                       elsif job.status == "FINISHED" 
-                               @pending_jobs.delete job
-                       end
-               end
 
-               # Move remote -> finished 
-               for job in @remote_jobs
-                       if job.status == "ERROR"
-                               @log.info "Job \"#{job.id}\" is stopped by ERROR" 
-                               @remote_jobs.delete job 
-                       elsif job.status == "FINISHED" 
-                               @remote_jobs.delete job
-                       end
+       # remove remote pkg server
+       def remove_sync_package_server( url, dist )
+               get_db_connection() do |db|
+                       row = db.select_one("SELECT distributions.id FROM sync_pkg_servers,distributions WHERE sync_pkg_servers.pkgsvr_url='#{url}' and distributions.name='#{dist}' and sync_pkg_servers.distribution_id = distributions.id")
+                       if row.nil? then return false end
+                       dist_id = row['id'];
+                       db.do("DELETE FROM sync_pkg_servers WHERE pkgsvr_url='#{url}' and distribution_id=#{dist_id}")
                end
 
-               # MOVE waiting -> finished
-               for job in @waiting_jobs
-                       if job.status == "ERROR"  then
-                               @waiting_jobs.delete( job )
-                               @log.info "Job \"#{job.id}\" is removed by internal error"
+               return true
+       end
+
+
+       def supported_os_list
+               result = []
+               get_db_connection() do |db|
+                       rows = db.select_all("SELECT * FROM supported_os")
+                       rows.each do |row|
+                               result.push row['name']
                        end
                end
 
-               # MOVE waiting -> working
-               if @waiting_jobs.count > 0 then
-                       
-                       # get available job
-                       job = get_available_job
-
-                       # available job not exist?, continue
-                       if ( job.nil? ) then return end
+               return result
+       end
 
-                       # oherwise, check remote server
-                       rserver = get_available_server( job )
 
-                       # request for build
-                       if rserver != nil and rserver == self then
+       # add new target OS.
+       # If already exist, return false , otherwise true
+       def add_supported_os( os_name )
+               os_category = Utils.get_os_category( os_name )
+               if os_category.nil? then return false end
 
-                               # change 
-                               @waiting_jobs.delete job
-                               @working_jobs.push job
+               get_db_connection() do |db|
+                       row = db.select_one("SELECT * FROM supported_os WHERE name='#{os_name}'")
+                       if not row.nil? then return false end
+                       db.do "INSERT INTO supported_os(os_category_id, name) SELECT os_category.id, '#{os_name}' FROM os_category WHERE os_category.name='#{os_category}'"
+               end
 
-                               # start build
-                               job.execute
-                               @log.info "Moved the job \"#{job.id}\" to working job list" 
+               return true
+               
+       end
 
-                       elsif rserver != nil  then
-                               if job.execute_remote( rserver ) then
 
-                                       # status change & job control
-                                       job.status = "REMOTE_WAITING"
-                                       @waiting_jobs.delete( job )
-                                       @remote_jobs.push( job )
-                                       @log.info "Moved the job \"#{job.id}\" to remote job list" 
-                               else
-                                       @log.info "Moving the job \"#{job.id}\" to remote failed" 
-                               end
-                       else
-                               #puts "No available server"
-                       end
+       # remove target OS.
+       def remove_supported_os( os_name )
+               get_db_connection() do |db|
+                       row = db.select_one("SELECT * FROM supported_os WHERE name='#{os_name}'")
+                       if row.nil? then return false end
+                       db.do("DELETE FROM supported_os WHERE name='#{os_name}'")
                end
 
-               #check the connection if the waiting job is not asynchronous job
-               for job in @waiting_jobs
-                       if not job.is_asynchronous_job? and not job.is_connected? then
-                               @waiting_jobs.delete( job )
-                               @log.info "Job \"#{job.id}\" is disconneted by user. Removed!"
-                       end
-               end
-               for job in @remote_jobs
-                       if not job.is_asynchronous_job? and not job.is_connected? then
-                               @remote_jobs.delete( job )
-                               @log.info "Job \"#{job.id}\" is disconneted by user. Removed!"
-                       end
-               end
-               
+               return true
        end
 
 
-       # select the job whith no build-dependency problem 
-       def get_available_job
-       
-               # gather all working jobs
-               all_working_jobs = [] + @working_jobs
-               all_working_jobs = all_working_jobs + @remote_jobs
-       
-               # for waiting jobs      
-               for job in @waiting_jobs
-                       blocked_by = []
-                       is_changed = false
-               
-                       # should not have same packages with workings
-                       # should not depend on workings
-                       # should not be depended by workings
-                       for wjob in all_working_jobs
-                               if job.has_same_packages?( wjob ) or
-                                       job.does_depend_on?( wjob ) or
-                                       job.does_depended_by?( wjob ) then
-       
-                                       blocked_by.push wjob
-                                       # if there are some changes, check it
-                                       if not job.blocked_by.include? wjob then is_changed = true end
-                               end
-                       end
-                               
-                       # if available , then FIFO      
-                       if blocked_by.empty? then
-                               job.blocked_by = []
-                               return job
-                       else
-                               # check count
-                               if blocked_by.count != job.blocked_by.count then is_changed = true end
-
-                               # if somthing changed, print it and save it
-                               if is_changed then
-                                       job.log.info( "Waiting for finishing following jobs:", Log::LV_USER)
-                                       for bjob in blocked_by  
-                                               job.log.info( " * #{wjob.id} #{wjob.pkginfo.packages[0].source}", Log::LV_USER)
-                                       end
-                                       job.blocked_by = blocked_by
-                               end
-                       end
+       def self.get_supported_os_id(db, os_name) 
+               row = db.select_one("SELECT * FROM supported_os WHERE name='#{os_name}'")
+               if not row.nil? then
+                       return row['id']
+               else
+                       return "NULL"
                end
-               
-               return nil      
        end
 
 
-       # get remote server     
+       # get remote server
        def get_available_server ( job )
                candidates = []
-               
-               # check local
-               if @working_jobs.count < @max_working_jobs and can_build?(job) then
+
+               # calculate empty rooms
+               # if sub job, his parent should be excluded
+               local_empty_rooms = @jobmgr.get_number_of_empty_room
+
+               if local_empty_rooms > 0 and can_build?(job) then
                        candidates.push self
                end
 
-               # if Local build job, just check local
-               if job.instance_of? LocalBuildJob then return candidates[0] end
-
-               # get availables
-               for server in @friend_servers
-                       # select only "RUNNING" & possible one
-                       if ( server.status == "RUNNING" and server.can_build?( job ) and
-                               server.waiting_jobs.count == 0 and 
-                               server.working_jobs.count < server.max_working_jobs )
-                               candidates.push server
+               # get availables server
+               # but, job must not be "REGISTER" and "MULTIBUILD" job
+               if job.type != "REGISTER" and job.type != "MULTIBUILD" then
+                       @remote_servers.each do |server|
+                               if ( server.status == "RUNNING" and server.can_build?( job ) and
+                                       not server.has_waiting_jobs and
+                                       server.get_file_transfer_cnt() == 0 and
+                                       server.get_number_of_empty_room > 0 )
+                                       candidates.push server
+                               end
                        end
                end
 
                best_server = candidates[0]
                if best_server.nil? or candidates.count == 1 then return best_server end
 
-               # get best 
+               # get best
                # it is better if working jobs count is less
-               max_empty_room = best_server.max_working_jobs - best_server.working_jobs.count
-               for server in candidates
-                       # check whether idle, use it 
-                       if server.working_jobs.count == 0 then return server end
+               max_empty_room = best_server.get_number_of_empty_room
+               candidates.each do |server|
+                       # check whether idle, use it
+                       if not server.has_working_jobs then return server end
 
                        # skip
                        if server == best_server then next end
-               
+
                        # compare remain rooms
-                       empty_room = server.max_working_jobs - server.working_jobs.count
+                       empty_room = server.get_number_of_empty_room
                        if empty_room > max_empty_room then
-                               max_empty_room = empty_root
+                               max_empty_room = empty_room
                                best_server = server
                        end
                end
-                
+
                return best_server
        end
 
@@ -483,8 +487,8 @@ class BuildServer
                if can_build? job then return true end
 
                #if not found, check friends
-               for server in @friend_servers
-                       if server.status == "RUNNING" and 
+               @remote_servers.each do |server|
+                       if server.status == "RUNNING" and
                                job.can_be_built_on? server.host_os then
                                return true
                        end
@@ -492,5 +496,271 @@ class BuildServer
 
                return false
        end
+
+
+       # return available working slot
+       def get_number_of_empty_room
+               return @jobmgr.get_number_of_empty_room
+       end
+
+
+       # check there are working jobs
+       def has_working_jobs
+               return @jobmgr.has_working_jobs
+       end
+
+
+       # check there are waiting jobs
+       def has_waiting_jobs
+               return @jobmgr.has_waiting_jobs
+       end
+
+       def get_dbversion
+               db_version = nil
+               begin
+                       db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd)
+                       db_version = db.select_one("SELECT (value) FROM server_configs WHERE property = 'db_version'")[0].to_i
+               rescue DBI::DatabaseError => e
+                       #puts e.errstr
+               ensure
+                       db.disconnect if db
+               end
+               return db_version
+       end
+
+       def db_upgrade
+               result = true
+               create = false
+               begin
+                       db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd)
+                       db_version = db.select_one("SELECT (value) FROM server_configs WHERE property = 'db_version'")[0].to_i
+                       if db_version.nil? then
+                               create = true
+                       else
+                               list = @db_migrate[db_version..@db_version]
+                               if not list.nil? then
+                                       list.each do |sql_list|
+                                               sql_list.each do |sql|
+                                                       db.do sql
+                                               end
+                                       end
+                               end
+                       end
+               rescue DBI::DatabaseError => e
+                       puts e.errstr
+                       result = false
+               ensure
+                       db.disconnect if db
+               end
+               if create then create_db end
+               return result
+       end
+
+       def gen_db()
+               case @db_dsn
+               when /^SQLite3:/ then puts "SQLite3 DB#{@db_dsn.split(':')[1]} generating"
+               when /^Mysql:/ then
+                       name = nil
+                       host = nil
+                       port = nil
+                       socket = nil
+                       flag = nil
+                       dsn = @db_dsn.split(':')
+                       if dsn[2].nil? then
+                               dsn[1].split(';').each do |attr|
+                                       case attr.split('=')[0].strip
+                                       when /database/i then
+                                               name = attr.split('=')[1].strip
+                                       when /host/i then
+                                               host = attr.split('=')[1].strip
+                                       when /port/i then
+                                               port = attr.split('=')[1].strip
+                                       when /socket/i then
+                                               socket = attr.split('=')[1].strip
+                                       when /flag/i then
+                                               flag = attr.split('=')[1].strip
+                                       else
+                                               etc = attr.split('=')[1].strip
+                                       end
+                               end
+                       else
+                               name = dsn[1].strip
+                               host = dsn[2].strip
+                       end
+
+                       File.open("create_db.txt","w") do |f|
+                               f.puts "GRANT ALL ON #{name}.* TO '#{@db_user}'@'%' IDENTIFIED BY '#{@db_passwd}';"
+                               f.puts "CREATE DATABASE #{name};"
+                       end
+
+                       if host.eql? "localhost" or host.eql? "127.0.0.1" then
+                               socket_str = ""
+                               socket_str = "--socket=#{socket}" if not socket.nil?
+                               puts "Mysql DB #{name} generating"
+                               system("mysql -h #{host} #{socket_str} -u #{@db_user} --password=#{@db_passwd} < create_db.txt")
+                       else
+                               port_str = ""
+                               port_str = "-P #{port}" if not port.nil?
+                               puts "Mysql DB #{name} generating"
+                               system("mysql -h #{host} #{port_str} -u #{@db_user} --password=#{@db_passwd} < create_db.txt")
+                       end
+               else puts "not support DB #{@db_dsn}"
+               end
+       end
+
+       def create_db()
+               gen_db()
+               result = get_db_connection() do |db|
+                       inc = db_inc
+                       post_fix = db_post_fix
+                       now = db_now
+
+                       # remove table
+                       db.tables.each do |table|
+                               db.do "DROP TABLE #{table}"
+                       end
+
+                       # create table
+                       db.do "CREATE TABLE server_configs ( id INTEGER PRIMARY KEY #{inc}, property VARCHAR(64) NOT NULL, value VARCHAR(256) )#{post_fix}"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('id','#{@id}')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('path','#{@path}')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('db_version','#{@db_version}')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('port','2222')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('max_working_jobs','2')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('send_mail','NO')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('keep_time','86400')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('pkg_sync_period','600')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('changelog_check','false')"
+                       db.do "INSERT INTO server_configs (property,value) VALUES ('job_log_url','')"
+                       db.do "CREATE TABLE os_category ( id INTEGER PRIMARY KEY #{inc}, name VARCHAR(32) NOT NULL UNIQUE ) #{post_fix}"
+                       db.do "INSERT INTO os_category (name) VALUES ( 'linux' )"
+                       db.do "INSERT INTO os_category (name) VALUES ( 'windows' )"
+                       db.do "INSERT INTO os_category (name) VALUES ( 'macos' )"
+
+                       PackageDistribution.create_table(db, inc, post_fix)
+
+                       # sync package server
+            db.do "CREATE TABLE sync_pkg_servers ( 
+                               id INTEGER PRIMARY KEY #{inc}, 
+                               distribution_id INTEGER NOT NULL, 
+                               pkgsvr_url VARCHAR(256), 
+                               period INTEGER, 
+                               description VARCHAR(255),
+                CONSTRAINT fk_sync_pkg_servers_distributions1 FOREIGN KEY ( distribution_id ) REFERENCES distributions ( id ) ) #{post_fix}"
+
+                       db.do "CREATE TABLE supported_os ( 
+                               id INTEGER PRIMARY KEY #{inc}, 
+                               os_category_id INTEGER NOT NULL, 
+                               name VARCHAR(32) NOT NULL UNIQUE,
+                               CONSTRAINT fk_supported_os_os_category1 FOREIGN KEY ( os_category_id ) REFERENCES os_category ( id ) ) #{post_fix}"
+
+                       RemoteBuildServer.create_table(db, inc, post_fix)
+
+                       # USERS/GROUPS
+                       # users
+                       db.do "CREATE TABLE users ( id INTEGER PRIMARY KEY #{inc}, name VARCHAR(32) NOT NULL UNIQUE, email VARCHAR(256), password_hash VARCHAR(256), password_salt VARCHAR(256) ) #{post_fix}"
+                       # groups
+                       db.do "CREATE TABLE groups ( id INTEGER PRIMARY KEY #{inc}, name VARCHAR(32) NOT NULL UNIQUE, admin VARCHAR(32) NOT NULL DEFAULT 'FALSE', description VARCHAR(256) )#{post_fix}"
+                       # user groups  (users -- groups)
+                       db.do "CREATE  TABLE user_groups ( user_id INTEGER NOT NULL, group_id INTEGER NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', PRIMARY KEY ( user_id, group_id ),
+                                       CONSTRAINT fk_users_has_groups_users1 FOREIGN KEY ( user_id ) REFERENCES users ( id ),
+                                       CONSTRAINT fk_users_has_groups_groups1 FOREIGN KEY ( group_id ) REFERENCES groups ( id )) #{post_fix}"
+
+                       db.do "INSERT INTO users (name,email,password_hash,password_salt) VALUES ('administrators','admin@user','$2a$10$H.w3ssI9KfuvNEXXp1qxD.b3Wm8alJG.HXviUofe4nErDn.TKUAka','$2a$10$H.w3ssI9KfuvNEXXp1qxD.')"
+                       db.do "INSERT INTO groups (name, admin, description) VALUES ('admin','TRUE','')"
+                       db.do "INSERT INTO user_groups (user_id, group_id) SELECT users.id,groups.id FROM users,groups WHERE users.email = 'admin@user' and groups.name = 'admin'"
+
+                       # PROJECTS
+                       CommonProject.create_table(db, inc, post_fix)
+                       GitBuildProject.create_table(db, post_fix)
+                       BinaryUploadProject.create_table(db, post_fix)
+                       db.do "CREATE TABLE group_project_accesses( 
+                               group_id INTEGER NOT NULL, 
+                               project_id INTEGER NOT NULL, 
+                               build VARCHAR(32) NOT NULL DEFAULT 'TRUE', 
+                               PRIMARY KEY ( group_id,project_id ),
+                               CONSTRAINT fk_groups_has_projects_groups1 FOREIGN KEY ( group_id ) REFERENCES groups ( id ),
+                               CONSTRAINT fk_groups_has_projects_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ) )#{post_fix}"
+
+                       # JOBS
+                       CommonJob.create_table(db, post_fix)
+               end
+
+               return result
+       end
+
+
+       def get_db_connection(transaction=true)
+               begin
+                       if @db_dsn =~ /^SQLite3:/ then
+                               @sqlite3_db_mutex.lock
+                               @db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd)
+                       else
+                               if @db.nil? or not @db.connected? then
+                                       @db = DBI.connect("DBI:#{@db_dsn}", @db_user, @db_passwd)
+                               end
+                       end
+                       if transaction then
+                               @db['AutoCommit'] = false
+                               begin
+                                       @db.transaction do |dbh|
+                                               yield dbh if block_given?
+                                       end
+                               ensure
+                                       @db['AutoCommit'] = true
+                               end
+                       else
+                               yield @db if block_given?
+                       end
+
+                       return true
+
+               rescue DBI::DatabaseError => e
+                       @log.error "DB loading failed!" if not @log.nil?
+                       @log.error e.errstr if not @log.nil?
+                       @log.error e.backtrace.inspect if not @log.nil?
+
+               ensure
+                       if @db_dsn =~ /^SQLite3:/ then
+                               @db.disconnect if @db
+                               @db = nil
+                               @sqlite3_db_mutex.unlock
+                       end
+               end
+
+               return false
+       end
+
+
+       def check_user_id_from_email(user_email)
+               get_db_connection() do |db|
+                       row = db.select_one("SELECT * FROM users WHERE email='#{user_email}'")
+                       if not row.nil?  then
+                               return row['id']
+                       else
+                               return -1
+                       end
+               end
+
+               return -1
+       end
+
+
+       def get_email_using_user_id(user_id)
+               get_db_connection() do |db|
+                       row = db.select_one("SELECT * FROM users WHERE id='#{user_id}'")
+                       if not row.nil?  then
+                               return row['email']
+                       else
+                               return -1
+                       end
+               end
+               return -1
+       end
+
+
+       def qualify_admin_to_access(prj_id)
+               # nothing to do, admin can change everything on web admin tool
+       end
 end
 
index b0b237bad3de86ec9080be8f5f65a6c95dd65eee..eabded1645f4a4c1e0472dd508bca0dba556232c 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  BuildServerController.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -34,7 +34,7 @@ class BuildServerController
        @@instance_map = {}
 
        # create
-       def self.create_server (id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id)
+       def self.create_server (id, path, ftpsvr_addr=nil, ftpsvr_port=nil, ftpsvr_username=nil, ftpsvr_passwd=nil)
 
                # check server config root
                check_build_server_root
@@ -45,24 +45,20 @@ class BuildServerController
                end
 
                # create new instance and return it
-               @@instance_map[id] = BuildServer.new( id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id )
-               
+               @@instance_map[id] = BuildServer.new( id, path, ftpsvr_addr, ftpsvr_port, ftpsvr_username, ftpsvr_passwd)
                # set default
-               @@instance_map[id].git_server_url="gerrithost:"
-               if Utils::HOST_OS == "windows" then
+               if Utils.is_windows_like_os(Utils::HOST_OS) then
                        @@instance_map[id].git_bin_path="/c/Program\\ Files/Git/bin/git.exe"
                else
                        @@instance_map[id].git_bin_path="/usr/bin/git"
                end
-               @@instance_map[id].allowed_git_branch=nil
-               @@instance_map[id].max_working_jobs= 2
-               @@instance_map[id].job_log_url=""
-               @@instance_map[id].pkgsvr_cache_path="#{path}/pkgsvr_cache"
-       
 
                # write config
                write_server_config( @@instance_map[id] )
 
+               # set logger
+               @@instance_map[id].log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{id}/log" )
+
                puts "Created new build server: \"#{id}\""
                return @@instance_map[id]
        end
@@ -78,31 +74,49 @@ class BuildServerController
                        FileUtils.rm_rf "#{BuildServer::CONFIG_ROOT}/#{id}"
                        @@instance_map[id] = nil
                        puts "Removed the server \"#{id}\""
+               else
+                       puts "The server \"#{id}\" does not exist!"
                end
-               
-               # remove local package server
-               local_pkgsvr = PackageServer.new( id )
-               local_pkgsvr.remove_server(id)  
+       end
 
+       def self.migrate_server (id, dsn, user, passwd)
+               # set DB environment
+               server = get_server(id)
+               server.db_dsn = dsn if not dsn.nil?
+               server.db_user = user if not user.nil?
+               server.db_passwd = passwd if not passwd.nil?
+
+               # check db
+               if migrate_db(server) then
+                       write_server_config(server)
+               end
        end
 
+       def self.migrate_db (server)
+               version = server.get_dbversion
+               if version.nil? then server.create_db end
+               return server.db_upgrade
+       end
 
        # get
        def self.get_server( id )
 
                # check instance first
                if not @@instance_map[id] == nil
-                       return @@instance_map[id] 
+                       return @@instance_map[id]
                end
 
-               # check server config 
-               if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{id}/server.cfg" 
-                       raise RuntimeError, "The server \"#{id}\" does not exist."
+               # check server config
+               if not File.exist? "#{BuildServer::CONFIG_ROOT}/#{id}/server.cfg"
+                       raise RuntimeError, "The server \"#{id}\" does not exist!"
                end
 
                # get server config and return its object
                @@instance_map[id] = read_server_config(id)
 
+               # set logger first
+               @@instance_map[id].log = Log.new( "#{BuildServer::CONFIG_ROOT}/#{id}/log" )
+
                return @@instance_map[id]
        end
 
@@ -110,24 +124,14 @@ class BuildServerController
        # start server
        def self.start_server( id, port = 2222 )
                server = get_server(id)
-       
-               # write run port        
+               migrate_db(server)
+               server.jobmgr.cancel_broken_status
+
+               # write run port
                server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}"
                f = File.open( "#{server_dir}/run", "w" )
                f.puts port
-               f.close 
-
-               # write run job 
-               if File.exist? "#{server_dir}/latest_job" then
-                       f = File.open( "#{server_dir}/latest_job", "r" )
-                       server.job_index = f.gets.strip.to_i + 1
-                       f.close 
-               else
-                       f = File.open( "#{server_dir}/latest_job", "w" )
-                       f.puts "0"
-                       server.job_index = 0
-                       f.close
-               end     
+               f.close
 
                # start
                server.port = port
@@ -137,29 +141,141 @@ class BuildServerController
 
        # stop server
        def self.stop_server( id )
+
+               # server
+               server = get_server(id)
+               migrate_db(server)
+               client = BuildCommClient.create( "127.0.0.1", server.port )
+               if client.nil? then
+                       puts "Server is not running!"
+                       return false
+               end
+
+               # send request
+               stop_ok = false
+               if client.send "STOP|#{server.password}" then
+                       # recevie & print
+                       mismatched = false
+                       result = client.read_lines do |l|
+                               puts l
+                               if l.include? "Password mismatched!" then
+                                       mismatched = true
+                               end
+                       end
+                       if result and not mismatched then
+                               stop_ok = true
+                       end
+               end
+
+               # terminate
+               client.terminate
+
+               if not stop_ok then
+                       puts "Server stop failed!"
+               end
+
+               return true
+       end
+
+       # upgrade server
+       def self.upgrade_server( id )
+
+               # server
+               server = get_server(id)
+               migrate_db(server)
+               client = BuildCommClient.create( "127.0.0.1", server.port )
+               if client.nil? then
+                       puts "Server is not running!"
+                       return false
+               end
+
+               # send request
+               upgrade_ok = false
+               if client.send "UPGRADE|#{server.password}" then
+                       # recevie & print
+                       mismatched = false
+                       result = client.read_lines do |l|
+                               puts l
+                               if l.include? "Password mismatched!" then
+                                       mismatched = true
+                               end
+                       end
+                       if result and not mismatched then
+                               upgrade_ok = true
+                       end
+               end
+
+               # terminate
+               client.terminate
+
+               if not upgrade_ok then
+                       puts "Server upgrade failed!"
+               end
+
+               return true
+       end
+
+       # request upgrade friends build server
+       def self.request_upgrade_server( id )
+
                server = get_server(id)
+               migrate_db(server)
+               server_dir = "#{BuildServer::CONFIG_ROOT}/#{id}"
+
+               if File.exist? "#{server_dir}/friends" then
+                       File.open( "#{server_dir}/friends", "r" ) do |f|
+                               f.each_line do |l|
+                                       if l.split(",").count < 2 then next end
+                                       ip = l.split(",")[0].strip
+                                       port = l.split(",")[1].strip
 
-               # if the server is not running => error
+                                       client = BuildCommClient.create( ip, port )
+                                       if client.nil? then
+                                               puts "Friend Server #{ip}:#{port} is not running!"
+                                               next
+                                       end
+                                       # send request
+                                       upgrade_ok = false
+                                       if client.send "UPGRADE|#{server.password}" then
+                                               # recevie & print
+                                               mismatched = false
+                                               result = client.read_lines do |l2|
+                                                       puts l2
+                                                       if l2.include? "Password mismatched!" then
+                                                               mismatched = true
+                                                       end
+                                               end
+                                               if result and not mismatched then
+                                                       upgrade_ok = true
+                                               end
+                                       end
+
+                                       # terminate
+                                       client.terminate
+
+                                       if upgrade_ok then
+                                               puts "Friend Server #{ip}:#{port} upgrade requested!"
+                                       else
+                                               puts "Friend Server #{ip}:#{port} upgrade failed!"
+                                       end
+                               end
+                       end
+               else
+                       puts "No Friend Server."
+               end
 
-               # request stop
+               return true
        end
 
 
        # add friend server
-       def self.add_friend_server( id, ip, port )
+       def self.add_remote_server( id, ip, port )
                server = get_server(id)
-               
+               migrate_db(server)
+
                # add
-               if server.add_friend_server( ip, port ) then
-
-                       # write config  
-                       server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}"
-                       f = File.open( "#{server_dir}/friends", "a" )
-                       f.puts "#{ip},#{port}"
-                       f.close 
-                       
+               if server.add_remote_server( ip, port ) then
                        puts "Friend server is added successfully!"
-                       
                        return true
                else
                        puts "Friend server already exists in list!"
@@ -168,87 +284,538 @@ class BuildServerController
        end
 
 
-       # build git repository and upload
-       def self.build_git( id, repository, commit, os, url, resolve )
+       # remove friend server
+       def self.remove_remote_server( id, ip, port )
+               server = get_server(id)
+               migrate_db(server)
 
-               # server
+               # add
+               if server.remove_remote_server( ip, port ) then
+                       puts "Friend server is removed successfully!"
+                       return true
+               else
+                       puts "Friend server does not exist in list!"
+                       return false
+               end
+       end
+
+
+       # add supported target os
+       def self.add_target_os( id, os_name )
+               # get server
                server = get_server(id)
-               client = BuildCommClient.create( "127.0.0.1", server.port )
-               if client.nil? then return false end
+               migrate_db(server)
 
-               # send request
-               client.send "BUILD,GIT,#{repository},#{commit},#{os}"
+               # add
+               if server.add_supported_os( os_name ) then
+                       puts "Target OS is added successfully!"
+                       return true
+               else
+                       puts "Target OS already exists in list!"
+                       return false
+               end
+       end
 
-               # recevie & print
-               client.print_stream
 
-               # terminate     
-               client.terminate
+       # remove supported target os
+       def self.remove_target_os( id, os_name )
+               # get server
+               server = get_server(id)
+               migrate_db(server)
 
-               return true
+               # add
+               if server.remove_supported_os( os_name ) then
+                       puts "Target OS is removed successfully!"
+                       return true
+               else
+                       puts "Target OS does not exist in list!"
+                       return false
+               end
+
+               server.quit
        end
 
 
-       # resolve git and build it and upload 
-       def resolve_git( id, repository, commit, os, url )
-               # server
+       # add distribution
+       def self.add_distribution( id, dist_name, pkgsvr_url, pkgsvr_ip, pkgsvr_port )
+               # get server
                server = get_server(id)
-               client = BuildCommClient.create( "127.0.0.1", server.port )
-               if client.nil? then return false end
+               migrate_db(server)
 
-               # send request
-               client.send "RESOLVE,GIT,#{repository},#{commit},#{os}" 
+               # add
+               if server.distmgr.add_distribution( dist_name, pkgsvr_url, pkgsvr_ip, pkgsvr_port ) then
+                       puts "Distribution is added successfully!"
+                       return true
+               else
+                       puts "Distribution already exists in list!"
+                       return false
+               end
+       end
 
-               # recevie & print
-               client.print_stream
 
-               # terminate     
-               client.terminate
+       # remove distribution
+       def self.remove_distribution( id, dist_name )
+               # get server
+               server = get_server(id)
+               migrate_db(server)
 
-               return true
+               # remove
+               if server.distmgr.remove_distribution( dist_name ) then
+                       puts "Distribution is removed successfully!"
+                       return true
+               else
+                       puts "Distribution does not exist in list!"
+                       return false
+               end
+       end
+
+
+       # lock distribution
+       def self.lock_distribution(id, dist_name)
+               # get server
+               server = get_server(id)
+               migrate_db(server)
+
+               # remove
+               if server.distmgr.set_distribution_lock(dist_name, true) then
+                       puts "Distribution is locked!"
+                       return true
+               else
+                       puts "Locking distribution failed!"
+                       return false
+               end
+       end
+
+       
+       # unlock distribution
+       def self.unlock_distribution(id, dist_name)
+               # get server
+               server = get_server(id)
+               migrate_db(server)
+
+               # remove
+               if server.distmgr.set_distribution_lock(dist_name, false) then
+                       puts "Distribution is unlocked!"
+                       return true
+               else
+                       puts "Unlocking distribution failed!"
+                       return false
+               end
+       end
+
+
+       # add remote package server
+       def self.add_sync_package_server(id, url, dist_name)
+               server = get_server(id)
+               migrate_db(server)
+
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
+               # add
+               if server.add_sync_package_server( url, dist_name ) then
+                       puts "Remote package server is added!"
+                       return true
+               else
+                       puts "The server already exists in list!"
+                       return false
+               end
+       end
+
+
+       def self.check_distribution_name(dist_name, server)
+               if (dist_name.nil? or dist_name.empty?) then
+                       dist_name = server.distmgr.get_default_distribution_name()
+               end
+               if dist_name.nil? or dist_name.empty? then
+                       puts "No distribution is defined!"
+                       return nil
+               end
+
+               return dist_name
+       end
+
+       # remove remote package server
+       def self.remove_sync_package_server(id, url, dist_name)
+               server = get_server(id)
+               migrate_db(server)
+
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
+               # remove
+               if server.remove_sync_package_server( url, dist_name ) then
+                       puts "Remote package server is removed!"
+                       return true
+               else
+                       puts "The server does not exist in list!"
+                       return false
+               end
+       end
+
+
+       # add project
+       def self.add_project( id, project_name, git_repos, git_branch, remote_server_id,
+                                                passwd, os_string, dist_name )
+               # get server
+               server = get_server(id)
+               migrate_db(server)
+
+               # get supported os for project.
+               # if not specified, all supported os of the server will be used
+               if os_string.nil? or os_string.empty? then
+                       os_list = server.supported_os_list
+               else
+                       os_list = os_string.strip.split(",")
+
+                       # check OS name
+                       os_list.each do |os|
+                               if not server.supported_os_list.include? os then
+                                       puts "Unsupported OS name \"#{os}\" is used!"
+                                       puts "Check the following supported OS list:"
+                                       server.supported_os_list.each do |s_os|
+                                               puts " * #{s_os}"
+                                       end
+
+                                       return false
+                               end
+                       end
+               end
+
+               # add
+               if git_repos.nil? or git_branch.nil? then
+                       puts "Git repository or branch must be specified!"
+                       return false
+               end
+
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
+               result = server.prjmgr.add_git_project( project_name, git_repos, git_branch, passwd, os_list, dist_name )
+               if result then
+                       puts "Adding project succeeded!"
+                       return true
+               else
+                       puts "Adding project failed!"
+                       return false
+               end
+       end
+
+
+       # add binary project
+       def self.add_binary_project( id, project_name, pkg_name, passwd, os_string, dist_name )
+               # get server
+               server = get_server(id)
+               migrate_db(server)
+
+               # get supported os for project.
+               # if not specified, all supported os of the server will be used
+               if os_string.nil? or os_string == "default" then
+                       os_list = server.supported_os_list
+               else
+                       os_list = os_string.strip.split(",")
+                       # check OS name
+                       os_list.each do |os|
+                               if not server.supported_os_list.include? os then
+                                       puts "Unsupported OS name \"#{os}\" is used!"
+                                       puts "Check the following supported OS list:"
+                                       server.supported_os_list.each do |s_os|
+                                               puts " * #{s_os}"
+                                       end
+
+                                       return false
+                               end
+                       end
+               end
+
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
+               # add
+               result = server.prjmgr.add_binary_project( project_name, pkg_name, passwd,
+                                                                                                 os_list, dist_name )
+               if result then
+                       puts "Adding project succeeded!"
+                       return true
+               else
+                       puts "Adding project failed!"
+                       return false
+               end
+       end
+
+
+       # remove project
+       def self.remove_project( id, project_name, dist_name )
+               # get server
+               server = get_server(id)
+               migrate_db(server)
+
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
+               result = server.prjmgr.remove_project( project_name, dist_name )
+               if result then
+                       puts "Removing project succeeded!"
+                       return true
+               else
+                       puts "Removing project failed!"
+                       return false
+               end
        end
 
 
-       # build local project and upload
-       def self.build_local( id, local_path, os, url, resolve )
+       # full build
+       def self.build_all_projects( id, dist_name )
+
                # server
                server = get_server(id)
+               migrate_db(server)
+
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
                client = BuildCommClient.create( "127.0.0.1", server.port )
-               if client.nil? then return false end
+               if client.nil? then
+                       puts "Server is not running!"
+                       return false
+               end
 
                # send request
-               client.send "BUILD,LOCAL,#{local_path},#{os}"
-
-               # recevie & print
-               client.print_stream
+               fullbuild_ok = false
+               if client.send "FULLBUILD|#{server.password}|#{dist_name}" then
+                       # recevie & print
+                       mismatched = false
+                       dist_not_found = false
+                       result = client.read_lines do |l|
+                               puts l
+                               if l.include? "Password mismatched!" then
+                                       mismatched = true
+                               end
+                               if l.include? "Distribution not found!" then
+                                       dist_not_found = true
+                               end
+                       end
+                       if result and not mismatched and not dist_not_found then
+                               fullbuild_ok = true
+                       end
+               end
 
-               # terminate     
+               # terminate
                client.terminate
 
+               if not fullbuild_ok then
+                       puts "Full build failed!"
+               end
+
                return true
        end
 
 
-       # resolve local project and  build it and upload
-       def resolve_local( path, os )
+       def self.register_package(id, file_path, dist_name)
                # server
                server = get_server(id)
-               client = BuildCommClient.create( "127.0.0.1", server.port )
-               if client.nil? then return false end
+               migrate_db(server)
 
-               # send request
-               client.send "RESOLVE,LOCAL,#{local_path},#{os}"
+               # check distribution
+               dist_name = check_distribution_name(dist_name, server)
+               if dist_name.nil? then return false end
+
+               # check file exist?
+               if not File.exist? file_path then
+                       puts "File not found!"
+                       return false
+               end
+               file_path = File.expand_path(file_path)
 
-               # recevie & print
-               client.print_stream
+               # send request
+               success = false
+               client = BuildCommClient.create( "127.0.0.1", server.port )
+               if client.nil? then
+                       puts "Server is not running!"
+                       return false
+               end
+               if client.send "REGISTER|BINARY-LOCAL|#{file_path}|#{server.password}|#{dist_name}" then
+                       # recevie & print
+                       mismatched = false
+                       result = client.read_lines do |l|
+                               puts l
+                               if l.include? "Password mismatched!" then
+                                       mismatched = true
+                               end
+                       end
+                       if result and not mismatched then
+                               success = true
+                       end
+               end
 
-               # terminate     
+               # terminate
                client.terminate
 
+               if not success then
+                       puts "Registering package failed!"
+               end
+
                return true
        end
 
+       # server
+       def self.query_server( id )
+               server = get_server(id)
+               migrate_db(server)
+               server.prjmgr.load()
+
+               puts "* REMOTE SERVER(S) *"
+               server.get_remote_servers.each do  |s|
+                       puts " * #{s.ip}:#{s.port}"
+               end
+               puts ""
+
+               puts "* SUPPORTED OS *"
+               server.supported_os_list.each do  |os|
+                       puts " * #{os}"
+               end
+               puts ""
+
+               puts "* DISTRIBUTION(S) *"
+               server.distmgr.get_all_distributions().each do  |d|
+                       puts " * #{d.name}"
+               end
+               puts ""
+
+               puts "* SYNC PACKAGE SERVER(S) *"
+               server.get_sync_package_servers.each do  |s|
+                       puts " * [#{s[1]}] #{s[0]}"
+               end
+               puts ""
+
+               puts "* PROJECT(S) *"
+               server.prjmgr.get_all_projects().each do  |p|
+                       puts " * [#{p.dist_name}]  #{p.name}"
+               end
+       end
+
+
+       # server
+       def self.set_server_attribute( id, attr, value )
+               result = true
+
+               if attr.nil? or attr.empty? or value.nil? or value.empty? then
+                       puts "Attribute/Value must be specified!"
+                       return false
+               end
+
+               server = get_server(id)
+               case attr
+               when "GIT_BIN_PATH"
+                       server.git_bin_path = value
+               when "MAX_WORKING_JOBS"
+                       server.jobmgr.max_working_jobs = value.to_i
+               when "JOB_LOG_URL"
+                       server.job_log_url = value
+               when "SEND_MAIL"
+                       server.send_mail = value
+               when "TEST_TIME"
+                       server.test_time = value.to_i
+               when "PASSWORD"
+                       server.password = value
+               when "JOB_KEEP_TIME"
+                       server.keep_time = value.to_i
+               when "FTP_ADDR"
+                       server.ftp_addr = value
+               when "FTP_PORT"
+                       server.ftp_port = value
+               when "FTP_USERNAME"
+                       server.ftp_username = value
+               when "FTP_PASSWD"
+                       server.ftp_passwd = value
+               when "CHANGELOG_CHECK"
+                       server.changelog_check = value
+               when "DB_DSN"
+                       case value
+                       when /^SQLite3:(.*)/i then
+                               if $1.strip.empty? then db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db"
+                               else db_dsn = "SQLite3:#{$1.strip}"
+                               end
+                       when /^Mysql:(.*)/i then
+                               db_dsn = "Mysql:#{$1}"
+                       else
+                               db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db"
+                       end
+                       server.db_dsn = db_dsn
+               when "DB_USER"
+                       server.db_user = value if not value.empty?
+               when "DB_PASSWORD"
+                       server.db_passwd = value if not value.empty?
+               else
+                       puts "Wrong attribute name!"
+                       result = false
+               end
+
+               if result then write_server_config( server ) end
+
+               return result
+       end
+
+
+       # server
+       def self.get_server_attribute( id, attr )
+               result = true
+
+               if attr.nil? or attr.empty? then
+                       puts "Attribute name must be specified!"
+                       return false
+               end
+
+               server = get_server(id)
+               case attr
+               when "GIT_BIN_PATH"
+                       puts server.git_bin_path
+               when "MAX_WORKING_JOBS"
+                       puts server.jobmgr.max_working_jobs
+               when "JOB_LOG_URL"
+                       puts server.job_log_url
+               when "SEND_MAIL"
+                       puts server.send_mail
+               when "TEST_TIME"
+                       puts server.test_time
+               when "PASSWORD"
+                       puts server.password
+               when "JOB_KEEP_TIME"
+                       puts server.keep_time
+               when "FTP_ADDR"
+                       puts server.ftp_addr
+               when "FTP_PORT"
+                       puts server.ftp_port
+               when "FTP_USERNAME"
+                       puts server.ftp_username
+               when "FTP_PASSWD"
+                       puts server.ftp_passwd
+               when "CHANGELOG_CHECK"
+                       puts server.changelog_check
+               when "DB_DSN"
+                       puts server.db_dsn
+               when "DB_USER"
+                       puts server.db_user
+               when "DB_PASSWORD"
+                       puts server.db_passwd
+               else
+                       puts "Wrong attribute name!"
+                       result = false
+               end
+
+               return result
+       end
+
+
+       #####################
        private
+       #####################
 
        # check build server config path
        def self.check_build_server_root
@@ -264,21 +831,24 @@ class BuildServerController
        def self.write_server_config( server )
                # create config folder
                server_dir = "#{BuildServer::CONFIG_ROOT}/#{server.id}"
-               FileUtils.mkdir_p( "#{server_dir}" )
+               if not File.exist? server_dir then
+                       FileUtils.mkdir_p( server_dir )
+               end
 
                # write configuration
                File.open( "#{server_dir}/server.cfg", "w" ) do |f|
                        f.puts "ID=#{server.id}"
                        f.puts "PATH=#{server.path}"
-                       f.puts "PSERVER_URL=#{server.pkgserver_url}"
-                       f.puts "PSERVER_ADDR=#{server.pkgserver_addr}"
-                       f.puts "PSERVER_ID=#{server.pkgserver_id}"
-                       f.puts "PSERVER_CACHE_PATH=#{server.pkgsvr_cache_path}"
-                       f.puts "GIT_SERVER_URL=#{server.git_server_url}"
                        f.puts "GIT_BIN_PATH=#{server.git_bin_path}"
-                       f.puts "ALLOWED_GIT_BRANCH=#{server.allowed_git_branch}"
-                       f.puts "MAX_WORKING_JOBS=#{server.max_working_jobs}"
-                       f.puts "JOB_LOG_URL=#{server.job_log_url}"
+                       f.puts "TEST_TIME=#{server.test_time}" if server.test_time > 0
+                       f.puts "PASSWORD=#{server.test_time}" if server.password != "0000"
+                       if not server.ftp_addr.nil? then
+                               f.puts "FTP_URL=ftp://#{server.ftp_username}:#{server.ftp_passwd}@#{server.ftp_addr}:#{server.ftp_port}"
+                       end
+                       f.puts "#only supports \"Mysql\" and \"SQLite3\""
+                       f.puts "DB_DSN=#{server.db_dsn}"
+                       f.puts "DB_USER=#{server.db_user}"
+                       f.puts "DB_PASSWORD=#{server.db_passwd}"
                end
        end
 
@@ -286,48 +856,62 @@ class BuildServerController
        # read server configuration
        def self.read_server_config( id )
                path=""
-               pkgsvr_url=""
-               pkgsvr_addr=""
-               pkgsvr_id=""
-               pkgsvr_cache_path=""
-               git_server_url="gerrithost:"
                git_bin_path="/usr/bin/git"
-               allowed_git_branch=""
-               max_working_jobs= 2
-               job_log_url=""
+               test_time=0
+               password="0000"
+               ftp_addr=nil
+               ftp_port=nil
+               ftp_username=nil
+               ftp_passwd=nil
+               db_dsn="SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db"
+               db_user=nil
+               db_passwd=nil
 
                # read configuration
                server_dir = "#{BuildServer::CONFIG_ROOT}/#{id}"
                File.open( "#{server_dir}/server.cfg", "r" ) do |f|
                        f.each_line do |l|
+                               if l.strip.start_with?("#") then next end
+                               idx = l.index("=") + 1
+                               length = l.length - idx
+
                                if l.start_with?("PATH=")
-                                       path = l.split("=")[1].strip
-                               elsif l.start_with?("PSERVER_URL=")
-                                       pkgsvr_url = l.split("=")[1].strip
-                               elsif l.start_with?("PSERVER_ADDR=")
-                                       pkgsvr_addr = l.split("=")[1].strip
-                               elsif l.start_with?("PSERVER_ID=")
-                                       pkgsvr_id = l.split("=")[1].strip
-                               elsif l.start_with?("PSERVER_CACHE_PATH=")
-                                       pkgsvr_cache_path = l.split("=")[1].strip
-                               elsif l.start_with?("GIT_SERVER_URL=")
-                                       git_server_url = l.split("=")[1].strip
+                                       path = l[idx,length].strip
                                elsif l.start_with?("GIT_BIN_PATH=")
-                                       git_bin_path = l.split("=")[1].strip
-                               elsif l.start_with?("ALLOWED_GIT_BRANCH=")
-                                       allowed_git_branch = l.split("=")[1].strip
-                               elsif l.start_with?("MAX_WORKING_JOBS=")
-                                       max_working_jobs = l.split("=")[1].strip.to_i
-                               elsif l.start_with?("JOB_LOG_URL=")
-                                       job_log_url = l.split("=")[1].strip
+                                       git_bin_path = l[idx,length].strip
+                               elsif l.start_with?("TEST_TIME=")
+                                       test_time = l[idx,length].strip.to_i
+                               elsif l.start_with?("PASSWORD=")
+                                       password = l[idx,length].strip.to_i
+                               elsif l.start_with?("FTP_URL=")
+                                       ftp_result = Utils.parse_ftpserver_url(l[idx,length].strip)
+                                       ftp_addr = ftp_result[0]
+                                       ftp_port = ftp_result[1]
+                                       ftp_username = ftp_result[2]
+                                       ftp_passwd = ftp_result[3]
+                               elsif l.start_with?("DB_DSN=")
+                                       case l[idx,length].strip
+                                       when /^SQLite3:(.*)/i then
+                                               if $1.strip.empty? then db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db"
+                                               else db_dsn = "SQLite3:#{$1.strip}"
+                                               end
+                                       when /^Mysql:(.*)/i then
+                                               db_dsn = "Mysql:#{$1}"
+                                       else
+                                               db_dsn = "SQLite3:#{BuildServer::CONFIG_ROOT}/#{id}/server.db"
+                                       end
+                               elsif l.start_with?("DB_USER=")
+                                       db_user = l[idx,length].strip if not l[idx,length].strip.empty?
+                               elsif l.start_with?("DB_PASSWORD=")
+                                       db_passwd = l[idx,length].strip if not l[idx,length].strip.empty?
                                else
-                                       next    
-                               end 
+                                       next
+                               end
                        end
                end
 
                # create server object
-               obj = BuildServer.new( id, path, pkgsvr_url, pkgsvr_addr, pkgsvr_id )
+               obj = BuildServer.new( id, path, ftp_addr, ftp_port, ftp_username, ftp_passwd )
 
                # check running port
                if File.exist? "#{server_dir}/run" then
@@ -337,40 +921,23 @@ class BuildServerController
                        f.close
                end
 
-               # check friend server
-               if File.exist? "#{server_dir}/friends" then
-                       File.open( "#{server_dir}/friends", "r" ) do |f|
-                               f.each_line do |l|
-                                       if l.split(",").count < 2 then next end
-                                       ip = l.split(",")[0].strip
-                                       port = l.split(",")[1].strip
-                                       obj.add_friend_server( ip, port.to_i )
-                               end
-                       end
-               end             
-
-               # set git server url
-               obj.git_server_url = git_server_url
-
                # set git binary path
                obj.git_bin_path = git_bin_path
-       
-               # set git binary path
-               obj.max_working_jobs = max_working_jobs
 
-               # set job log url
-               obj.job_log_url = job_log_url
+               # set test time
+               obj.test_time = test_time
 
-               # set allowed git branch name
-               obj.allowed_git_branch = allowed_git_branch
+               # set password
+               obj.password = password
 
-               # set package server path
-               pkgsvr_cache_path = (pkgsvr_cache_path.empty? ? "#{path}/pkgsvr_cache":pkgsvr_cache_path)
-               obj.pkgsvr_cache_path= pkgsvr_cache_path
+               # DB settring
+               obj.db_dsn = db_dsn if not db_dsn.nil?
+               obj.db_user = db_user
+               obj.db_passwd = db_passwd
 
                # save config
-               write_server_config( obj )
-               
+               #write_server_config( obj )
+
                # create object & return it
                return obj
        end
diff --git a/src/build_server/BuildServerException.rb b/src/build_server/BuildServerException.rb
new file mode 100644 (file)
index 0000000..8faed9a
--- /dev/null
@@ -0,0 +1,31 @@
+class BuildServerException < Exception
+       @@err_msgs = {
+               "ERR001" => "Invalid request format is used!",
+               "ERR002" => "Distribution not found!",
+               "ERR003" => "Unsupported OS name used!",
+               "ERR004" => "User account not found!",
+               "ERR005" => "Project access denied!",
+               "ERR006" => "Job creation failed!",
+               "ERR007" => "No supported OS defined in build server!",
+               "ERR008" => "Distribution locked!",
+               "ERR009" => "Project not found!",
+               "ERR010" => "Build operation not allowed on this project type!",
+               "ERR011" => "Project password required!",
+               "ERR012" => "Project password not matched!",
+               "ERR013" => "Project from file-name/distribution not found!",
+               "ERR014" => "Job cancel failed!",
+               "ERR015" => "Server password not matched!"
+       }
+
+       def initialize(code)
+               @err_code = code
+       end
+
+       def err_message()
+               if not message().nil? and not message().empty? then
+                       return "Error: #{@@err_msgs[@err_code]}: #{message()}"
+               else
+                       return "Error: #{@@err_msgs[@err_code]}"
+               end
+       end
+end
index 55fc3708e414570e1c2ffa58c57f0cef4cb98944..455a48b289855ab6d38c7dd6e75c658fe4738d80 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  BuildServerOptionParser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -26,92 +26,366 @@ Contributors:
 - S-Core Co., Ltd
 =end
 
+$LOAD_PATH.unshift File.dirname(__FILE__)+"/src/common"
 require 'optparse'
+require 'utils'
+
+class BuildServerUsage
+       CREATE="build-svr create -n <server name> [-t <ftp server url>]"
+       REMOVE="build-svr remove -n <server name>"
+       MIGRATE="build-svr migrate -n <server name> [--dsn <db dsn> [--dbuser <db_user> --dbpassword <db_password>] ]"
+       START="build-svr start -n <server name> -p <port>"
+       STOP="build-svr stop -n <server name>"
+       UPGRADE="build-svr upgrade -n <server name> [-D <distribution name>]"
+       ADD_SVR="build-svr add-svr -n <server name> -d <friend server address>"
+       REMOVE_SVR= "build-svr remove-svr -n <server name> -d <friend server address>"
+       ADD_OS= "build-svr add-os -n <server name> -o <os>"
+       REMOVE_OS="build-svr remove-os -n <server name> -o <os>"
+       ADD_DIST= "build-svr add-dist -n <server name> -D <distribution name> -u <package server url> -d <package server address>"
+       REMOVE_DIST="build-svr remove-dist -n <server name> -D <distribution name>"
+       LOCK_DIST="build-svr lock-dist -n <server name> -D <distribution name>"
+       UNLOCK_DIST="build-svr unlock-dist -n <server name> -D <distribution name>"
+       ADD_SYNC="build-svr add-sync -n <server name> -u <remote pkg server url> [--dist <distribution>]"
+       REMOVE_SYNC="build-svr remove-sync -n <server name> -u <remote pkg server url> [--dist <distribution>]"
+       ADD_PRJ="build-svr add-prj -n <server name> -N <project name> (-g <git repository> -b <git branch>|-P <package name>) [-w <password>] [-o <os list>] [--dist <distribution>]"
+       REMOVE_PRJ="build-svr remove-prj -n <server name> -N <project name> [--dist <distribution>]"
+       FULLBUILD="build-svr fullbuild -n <server name> [--dist <distribution>]"
+       REGISTER="build-svr register -n <server name> -P <package file> [--dist <distribution>]"
+       QUERY="build-svr query -n <server name>"
+       SET_ATTR="build-svr set-attr -n <server name> -A <attribute> -V <value>"
+       GET_ATTR="build-svr get-attr -n <server name> -A <attribute>"
+end
+
+def option_error_check( options )
+       case options[:cmd]
+
+       when "create"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::CREATE
+               end
+
+       when "remove"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE
+               end
+
+       when "migrate"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::MIGRATE
+               end
+
+       when "start"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:port].nil? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::START
+               end
+
+       when "stop"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::STOP
+               end
+
+       when "upgrade"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::UPGRADE
+               end
+
+       when "add-svr"
+               if options[:name].nil? or options[:name].empty? or
+                       (options[:domain].nil? or options[:domain].empty?) then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::ADD_SVR
+               end
+
+       when "remove-svr"
+               if options[:name].nil? or options[:name].empty? or
+                       (options[:domain].nil? or options[:domain].empty?) then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_SVR
+               end
+
+       when "add-os"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:os].nil? or options[:os].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::ADD_OS
+               end
+
+       when "remove-os"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:os].nil? or options[:os].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_OS
+               end
+
+       when "add-dist"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:dist].nil? or options[:dist].empty? or
+                       options[:url].nil? or options[:url].empty? or
+                       options[:domain].nil? or options[:domain].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::ADD_DIST
+               end
+
+       when "remove-dist"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:dist].nil? or options[:dist].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_DIST
+               end
+
+       when "lock-dist"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:dist].nil? or options[:dist].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::LOCK_DIST
+               end
+
+       when "unlock-dist"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:dist].nil? or options[:dist].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::UNLOCK_DIST
+               end
+
+       when "add-sync"
+               if options[:name].nil? or options[:name].empty? or
+                       (options[:url].nil? or options[:url].empty?) then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::ADD_SYNC
+               end
+
+       when "remove-sync"
+               if options[:name].nil? or options[:name].empty? or
+                       (options[:url].nil? or options[:url].empty?) then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_SYNC
+               end
+
+       when "add-prj"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:pid].nil? or options[:pid].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::ADD_PRJ
+               end
+
+       when "remove-prj"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:pid].nil? or options[:pid].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REMOVE_PRJ
+               end
+
+       when "fullbuild"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::FULLBUILD
+               end
+
+       when "register"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:package].nil? or options[:package].empty?  then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::REGISTER
+               end
+
+       when "query"
+               if options[:name].nil? or options[:name].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::QUERY
+               end
+
+       when "set-attr"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:attr].nil? or options[:attr].empty? or
+                       options[:value].nil? or options[:value].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::SET_ATTR
+               end
+
+       when "get-attr"
+               if options[:name].nil? or options[:name].empty? or
+                       options[:attr].nil? or options[:attr].empty? then
+                       raise ArgumentError, "Usage: " + BuildServerUsage::SET_ATTR
+               end
 
-def option_parse 
-    options = {}
-    banner = "Usage: build-svr {create|remove|start|build|help} ..." + "\n" \
-        + "\t" + "build-svr create -n <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 build -n <name> [-l <local-path>] [-g <git-repository> -c <git-commit>] [-o <os>] [-r]" + "\n"  \
-        + "\t" + "build-svr add -n <name> [-d <frined-svr-domain> -p <friend-svr port>]" + "\n" 
-
-    optparse = OptionParser.new do|opts|
-        # Set a banner, displayed at the top
-        # of the help screen.
-
-               opts.banner = banner 
-
-        opts.on( '-n', '--name <name>', 'build server name' ) do|name|
-            options[:name] = name 
-        end
-        
-               opts.on( '-u', '--url <pkg-server-url>', 'package server URL: http://xxx/yyy/zzz' ) do|url|
-            options[:url] = url 
-        end
-
-               opts.on( '-d', '--domain <pkg/friend-svr domain>', 'package svr or friend svr ip or ssh alias' ) do|domain|
-            options[:domain] = domain
-        end
-               
-               opts.on( '-i', '--id <pkg-server-id>', 'package server id' ) do|pid|
-            options[:pid] = pid
-        end
-
-        options[:port] = 2222
-               opts.on( '-p', '--port <port>', 'port' ) do|port|
-            options[:port] = port.strip.to_i
-        end
-               
-               opts.on( '-l', '--local <local-path>', 'local source path' ) do|path|
-            options[:local] = path
-        end
-               
-               opts.on( '-g', '--git <git-repository>', 'git repository gerrithost:/xxx/yyy/zzz' ) do|git|
-            options[:git] = git
-        end
-
-               opts.on( '-c', '--commit <git-commit>', 'git commit id/tag' ) do|git|
-               if git.start_with? "/" then
-                       git = git[1..-1]
-               end
-            options[:commit] = git
-        end
-
-               opts.on( '-o', '--os <operating system>', 'target operating system linux/windows/darwin' ) do|os|
-            options[:os] = os
-        end
-               
-        options[:resolve] = false
-               opts.on( '-r', '--resolve', 'reverse build dependency fail resolve' ) do
-            options[:resolve] = true
-        end
+       else
+               raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
+       end
+end
+
+def option_parse
+       options = {}
+       banner = "Build-server administer service command-line tool." + "\n" \
+               + "\n" + "Usage: build-svr <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" + "migrate       build-server DB migrate." + "\n" \
+               + "\t" + "start         Start the build-server." + "\n" \
+               + "\t" + "stop          Stop the build-server." + "\n" \
+               + "\t" + "upgrade       Upgrade the build-server include friends." + "\n" \
+               + "\t" + "add-svr       Add remote build/package server for support multi-OS or distribute build job." + "\n" \
+               + "\t" + "remove-svr    Remove remote build/package server for support multi-OS or distribute build job." + "\n" \
+               + "\t" + "add-os        Add supported OS." + "\n" \
+               + "\t" + "remove-os     Remove supported OS." + "\n" \
+               + "\t" + "add-dist      Add distribution." + "\n" \
+               + "\t" + "remove-dist   Remove distribution." + "\n" \
+               + "\t" + "lock-dist     Lock distribution." + "\n" \
+               + "\t" + "unlock-dist   Unlock distribution." + "\n" \
+               + "\t" + "add-sync      Add package repository URL to synchronize with." + "\n" \
+               + "\t" + "remove-sync   Remove package repository URL." + "\n" \
+               + "\t" + "add-prj       Add project to build." + "\n" \
+               + "\t" + "remove-prj    Remove project." + "\n" \
+               + "\t" + "register      Register the package to the build-server." + "\n" \
+               + "\t" + "fullbuild     Build all your projects and upload them to package server." + "\n" \
+               + "\t" + "query         Show build server configuration." + "\n" \
+               + "\t" + "set-attr      Set build server atribute." + "\n" \
+               + "\t" + "get-attr      Get build server atribute." + "\n" \
+               + "\n" + "Subcommand usage:" + "\n" \
+               + "\t" + BuildServerUsage::CREATE + "\n" \
+               + "\t" + BuildServerUsage::REMOVE + "\n" \
+               + "\t" + BuildServerUsage::MIGRATE + "\n" \
+               + "\t" + BuildServerUsage::START + "\n" \
+               + "\t" + BuildServerUsage::STOP + "\n" \
+               + "\t" + BuildServerUsage::UPGRADE + "\n" \
+               + "\t" + BuildServerUsage::ADD_SVR + "\n" \
+               + "\t" + BuildServerUsage::REMOVE_SVR + "\n" \
+               + "\t" + BuildServerUsage::ADD_OS + "\n" \
+               + "\t" + BuildServerUsage::REMOVE_OS + "\n" \
+               + "\t" + BuildServerUsage::ADD_DIST + "\n" \
+               + "\t" + BuildServerUsage::REMOVE_DIST + "\n" \
+               + "\t" + BuildServerUsage::LOCK_DIST + "\n" \
+               + "\t" + BuildServerUsage::UNLOCK_DIST + "\n" \
+               + "\t" + BuildServerUsage::ADD_SYNC + "\n" \
+               + "\t" + BuildServerUsage::REMOVE_SYNC + "\n" \
+               + "\t" + BuildServerUsage::ADD_PRJ + "\n" \
+               + "\t" + BuildServerUsage::REMOVE_PRJ + "\n" \
+               + "\t" + BuildServerUsage::FULLBUILD + "\n" \
+               + "\t" + BuildServerUsage::REGISTER + "\n" \
+               + "\t" + BuildServerUsage::QUERY + "\n" \
+               + "\t" + BuildServerUsage::SET_ATTR + "\n" \
+               + "\t" + BuildServerUsage::GET_ATTR + "\n" \
+               + "\n" + "Options:" + "\n"
+
+       optparse = OptionParser.new(nil, 32, ' '*8) do|opts|
+               # Set a banner, displayed at the top
+               # of the help screen.
+
+               opts.banner = banner
+
+               opts.on( '-n', '--name <server name>', 'build server name' ) do|name|
+                       options[:name] = name
+               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( '-d', '--address <server address>', 'server address: 127.0.0.1:2224' ) do|domain|
+                       options[:domain] = domain
+               end
+
+               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
+
+               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[:dist] = ""
+               opts.on( '-D', '--dist <distribution name>', 'distribution name' ) do |dist|
+                       options[:dist] = dist
+               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( '-A', '--attr <attribute name>', 'attribute' ) do |attr|
+                       options[:attr] = attr
+               end
+
+               options[:db_dsn] = nil
+               opts.on( '--dsn <dsn>', 'Data Source Name ex) mysql:host=localhost;database=test' ) do |dsn|
+                       options[:db_dsn] = dsn
+               end
+
+               options[:db_user] = nil
+               opts.on( '--dbuser <user>', 'DB user id' ) do |user|
+                       options[:db_user] = user
+               end
+
+               options[:db_passwd] = nil
+               opts.on( '--dbpassword <password>', 'DB password' ) do |password|
+                       options[:db_passwd] = password
+               end
+
+
+               opts.on( '-V', '--value <value>', 'value' ) do |value|
+                       options[:value] = value
+               end
 
                opts.on( '-h', '--help', 'display this information' ) do
-            puts opts
+                       opts.help.split("\n").each {|op| puts op if not op.include? "--CHILD"}
+                       exit
+               end
+
+               opts.on( '-v', '--version', 'display version' ) do
+                       puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
                        exit
-        end
-               
-    end
-    
-       cmd = ARGV[0] 
+               end
+
+               opts.on( '-C', '--CHILD', 'child process' ) do
+                       options[:child] = true
+               end
 
-    if cmd.eql? "create" or cmd.eql? "remove" or cmd.eql? "start" or 
-               cmd.eql? "build" or cmd.eql? "add" or
-                cmd =~ /(help)|(-h)|(--help)/ then
+       end
 
-        if cmd.eql? "help" then 
-                       ARGV[0] = "-h" 
+       cmd = ARGV[0]
+       if cmd.eql? "create" or cmd.eql? "remove" or
+               cmd.eql? "start" or cmd.eql? "upgrade" or
+               cmd.eql? "stop" or cmd.eql? "migrate" or
+               cmd.eql? "add-svr" or cmd.eql? "remove-svr" or
+               cmd.eql? "add-os" or cmd.eql? "remove-os" or
+               cmd.eql? "add-dist" or cmd.eql? "remove-dist" or
+               cmd.eql? "lock-dist" or cmd.eql? "unlock-dist" or
+               cmd.eql? "add-sync" or cmd.eql? "remove-sync" or
+               cmd.eql? "add-prj" or cmd.eql? "remove-prj" or
+               cmd.eql? "fullbuild" or cmd.eql? "register" or
+               cmd.eql? "query" or
+               cmd.eql? "set-attr" or cmd.eql? "get-attr" or
+               cmd =~ /(-v)|(--version)/ or
+               cmd =~ /(help)|(-h)|(--help)/ then
+
+               if cmd.eql? "help" then
+                       ARGV[0] = "-h"
                end
 
-        options[:cmd] = ARGV[0]
-    else
-        raise ArgumentError, banner
-    end
+               options[:cmd] = ARGV[0]
+       else
+               raise ArgumentError, "Usage: build-svr <SUBCOMMAND> [OPTS] or build-svr -h"
+       end
+
+       optparse.parse!
+
+       option_error_check options
 
-    optparse.parse!
-   
-    return options
-end 
+       return options
+end
 
diff --git a/src/build_server/CommonJob.rb b/src/build_server/CommonJob.rb
new file mode 100644 (file)
index 0000000..5a624df
--- /dev/null
@@ -0,0 +1,277 @@
+=begin
+
+ CommonJob.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 "time"
+$LOAD_PATH.unshift File.dirname(__FILE__)
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+require "utils.rb"
+
+class CommonJob
+
+       attr_accessor :id, :server, :log, :status, :priority
+       attr_accessor :os, :type, :pre_jobs, :user_id
+       USER_JOB_PRIORITY = 100
+       AUTO_JOB_PRIORITY = 0
+
+       # initialize
+       public
+       def initialize(server, id=nil)
+               @server = server
+               if not server.jobmgr.nil? then
+                       @id = server.jobmgr.get_new_job_id()
+               else
+                       @id = 0
+               end
+
+               @parent = nil
+               @sub_jobs = []
+               @priority = USER_JOB_PRIORITY # higher numbered job get priority
+               @os = "Unknown"
+               @type = "Unknown"
+               @pre_jobs = [] #pre-requisite jobs
+               @project = nil
+               @user_id = 1
+
+               @status = "JUST_CREATED"
+               @log = nil
+
+               @start_time = Time.now
+               @end_time = nil
+
+               @sub_pid = 0
+       end
+
+
+       # set parent
+       public
+       def set_parent_job( parent )
+               @parent = parent
+       end
+
+
+       # get parent
+       public
+       def get_parent_job()
+               return @parent
+       end
+
+
+       # check this job has a parent job
+       public
+       def is_sub_job?
+               return (not @parent.nil?)
+       end
+
+
+       # get all sub jobs
+       public
+       def get_sub_jobs
+               return @sub_jobs
+       end
+
+
+       # add sub job
+       public
+       def add_sub_job( job )
+               @sub_jobs.push job
+               # this will make sub-job to share build-root of parent
+               job.set_parent_job( self )
+       end
+
+
+       # create logger
+       public
+       def create_logger( second_out, verbose = false )
+               @log = JobLog.new( self, second_out, verbose )
+               return @log
+       end
+
+
+       public
+       def get_project()
+               return @project
+       end
+
+
+       public
+       def set_project( project )
+               @project = project
+       end
+
+       public
+       def get_user_email
+               return @server.get_email_using_user_id(@user_id)
+       end
+
+
+       # execute
+       public
+       def execute(sync=false)
+
+               # create a thread for job
+               @thread = Thread.new do
+                       begin
+                               job_main()
+
+                               # parent job will call sub job's terminate method
+                               if not is_sub_job? then terminate() end
+                       rescue => e
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                       end
+               end
+
+               if sync then
+                       @thread.join
+               end
+
+               return true
+       end
+
+
+       #terminate
+       public
+       def terminate()
+               #do noting
+       end
+
+
+       #cancel
+       public
+       def cancel()
+               # kill sub process if exist?
+               kill_sub_process()
+       end
+
+
+       # show progress
+       public
+       def progress
+               # do nothing
+               return ""
+       end
+
+
+       # create process to execute command
+       public
+       def execute_command(cmd)
+               # execute
+               pid, status = Utils.execute_shell_with_log(cmd, @log.path, false)
+               @sub_pid = pid
+
+               # wait for finish
+               begin
+                       pid, status = Process.waitpid2(pid)
+               rescue Errno::ECHILD
+                       # pid is not exist
+                       # do notting
+               end
+               @sub_pid = 0
+
+               # return
+               return pid, status
+       end
+
+
+       public
+       def self.create_table(db, post_fix)
+               db.do "CREATE TABLE jobs ( 
+                       id INTEGER PRIMARY KEY, 
+                       project_id INTEGER, 
+                       user_id INTEGER NOT NULL, 
+                       supported_os_id INTEGER, 
+                       distribution_id INTEGER,
+                       parent_job_id INTEGER, 
+                       remote_build_server_id INTEGER, 
+                       source_id INTEGER, 
+                       jtype VARCHAR(32) NOT NULL, 
+                       status VARCHAR(32) NOT NULL DEFAULT 'JUST_CREATED', 
+                       start_time DATETIME, 
+                       end_time DATETIME,
+                       CONSTRAINT fk_jobs_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ),
+                       CONSTRAINT fk_jobs_users1 FOREIGN KEY ( user_id ) REFERENCES users ( id ),
+                       CONSTRAINT fk_jobs_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ),
+                       CONSTRAINT fk_jobs_distributions1 FOREIGN KEY ( distribution_id ) REFERENCES distributions ( id ),
+                       CONSTRAINT fk_jobs_jobs1 FOREIGN KEY ( parent_job_id ) REFERENCES jobs ( id ),
+                       CONSTRAINT fk_jobs_sources1 FOREIGN KEY ( source_id ) REFERENCES sources ( id ), 
+                       CONSTRAINT fk_jobs_remote_build_servers1 FOREIGN KEY ( remote_build_server_id ) REFERENCES remote_build_servers ( id ) )#{post_fix}"
+       end
+
+
+       # save to db
+       public
+       def save(db, now)
+
+               prj_id = @project.nil? ? "NULL" : @project.get_project_id()
+               row=db.select_one("SELECT * FROM jobs WHERE id=#{@id}")
+               if row.nil? then
+                       start_time = @start_time.strftime("%F %T")
+                       os_id = BuildServer.get_supported_os_id(db, @os)
+                       dist_id = PackageDistribution.get_distribution_id(db, get_distribution_name())
+                       parent_id = @parent.nil? ? "NULL" : @parent.id
+                       db.do "INSERT INTO jobs(id,project_id,user_id,supported_os_id, distribution_id, parent_job_id,jtype,status,start_time) 
+                               VALUES (#{@id},#{prj_id},#{@user_id},#{os_id},#{dist_id},#{parent_id},'#{@type}','#{@status}',#{now})"
+               else
+                       remote_bs_id = (@type == "BUILD" and not get_remote_server().nil?) ? 
+                               get_remote_server().id : "NULL"
+                       if @status == "FINISHED" and not @project.nil? and 
+                               (@type == "BUILD" or @type == "REGISTER") then
+                               source_id = @project.get_source_id_from_ver(pkginfo.get_version(),db)
+                               db.do "UPDATE jobs SET source_id=#{source_id} WHERE id=#{@id}"
+                       end
+                       db.do "UPDATE jobs SET status='#{@status}',remote_build_server_id=#{remote_bs_id} WHERE id=#{@id}"
+                       if @status == "FINISHED" or @status == "ERROR" or @status == "CANCELED" then
+                               @end_time = Time.now.strftime("%F %T")
+                               db.do "UPDATE jobs SET end_time=#{now} WHERE id=#{@id}"
+                       end
+               end
+       end
+
+
+       #
+       # PROTECTED METHODS
+       #
+
+       # main module
+       protected
+       def job_main
+               # do nothing
+       end
+
+
+       protected
+       def kill_sub_process()
+               if @sub_pid != 0 then
+                       if not @log.nil? then
+                               @log.info("Killing sub process! id = #{@sub_pid}")
+                       end
+                       Utils.kill_process(@sub_pid)
+               end
+       end
+end
diff --git a/src/build_server/CommonProject.rb b/src/build_server/CommonProject.rb
new file mode 100644 (file)
index 0000000..a2b46ac
--- /dev/null
@@ -0,0 +1,355 @@
+=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, :dist_name, :path
+
+       # initialize
+       def initialize( name, type, server, os_list, dist_name="BASE" )
+               @prj_id = -1
+               @name = name
+               @type = type
+               @passwd = ""
+               @os_list = os_list
+               @server = server
+               @dist_name = dist_name
+               @source_info = {}
+               @package_info = {}
+               if @dist_name == "BASE" then
+                       @path = "#{@server.path}/projects/#{@name}"
+               else
+                       @path = "#{@server.path}/projects/#{@dist_name}/#{@name}"
+               end
+       end
+
+
+       def ==(y)
+               @name == y.name and @dist_name = y.dist_name
+       end
+
+
+       def init()
+               # create project directory if not exist
+               if not File.exist? @path then FileUtils.mkdir_p @path end
+       end
+
+
+       #return passwd
+       def is_passwd_set?()
+               return ( not @passwd.empty? )
+       end
+
+
+       def passwd_match?(word)
+               if not is_passwd_set? then return true end
+
+               if word.eql? @passwd then
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       def set_source_info(info)
+               @source_info = info
+       end
+
+
+       def save_source_info(ver, info)
+               @source_info[ver] = info
+
+               # save to db
+               @server.get_db_connection() do |db|
+                       save_source_info_internal(ver, info, db)
+               end
+       end
+
+
+       def get_source_info(ver)
+               return @source_info[ver]
+       end
+
+       
+       def set_package_info(info)
+               @package_info = info
+       end
+
+
+       def save_package_info(ver, pkg_name, pkg_os)
+               if @package_info[ver].nil? then
+                       @package_info[ver] = []
+               end
+               @package_info[ver].push [pkg_name, pkg_os]
+
+               # save to db
+               @server.get_db_connection() do |db|
+                       save_package_info_internal(ver, pkg_name, pkg_os, db)
+               end
+       end
+
+
+       # get latest package version
+       def get_latest_version()
+               versions = @package_info.keys
+               if not versions.empty? then
+                       versions.sort! {|x,y| Version.new(x).compare(Version.new(y)) }
+                       return versions[-1]
+               else
+                       return nil
+               end
+       end
+
+
+       # get all package version
+       def get_all_versions()
+               return @package_info.keys
+       end
+
+
+       def include_package?(pkg_name, ver=nil, os=nil)
+               # check version first
+               if not ver.nil? then
+                       ver = get_latest_version()
+               end
+
+               if ver.nil? or @package_info[ver].nil? then return false end
+               if not os.nil? and not @os_list.include? os then return false end
+
+               # check name and version
+               @package_info[ver].each do |pkg|
+                       if pkg_name == pkg[0] and os == pkg[1] then
+                               return true
+                       end
+               end
+
+               return false
+       end
+
+
+       def set_project_id(id)
+               @prj_id = id
+       end
+
+
+       def get_project_id()
+               return @prj_id
+       end
+
+       def self.create_table(db, inc, post_fix) 
+               db.do "CREATE TABLE projects ( 
+                       id INTEGER PRIMARY KEY #{inc}, 
+                       distribution_id INTEGER NOT NULL, 
+                       user_id INTEGER,
+                       name VARCHAR(32) NOT NULL, 
+                       ptype VARCHAR(32) NOT NULL, 
+                       password VARCHAR(32),
+                       CONSTRAINT fk_projects_users1 FOREIGN KEY ( user_id ) REFERENCES users ( id ),
+                       CONSTRAINT fk_projects_distributions1 FOREIGN KEY ( distribution_id ) REFERENCES distributions ( id ) )#{post_fix}"
+
+               db.do "CREATE TABLE project_os ( 
+                       project_id INTEGER NOT NULL, 
+                       supported_os_id INTEGER NOT NULL, 
+                       PRIMARY KEY ( project_id,supported_os_id ),
+                       CONSTRAINT fk_projects_has_supported_os_projects FOREIGN KEY ( project_id ) REFERENCES projects ( id ),
+                       CONSTRAINT fk_projects_has_supported_os_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ) )#{post_fix}"
+
+               db.do "CREATE TABLE sources ( 
+                       id INTEGER PRIMARY KEY #{inc}, 
+                       project_id INTEGER NOT NULL, 
+                       pkg_ver VARCHAR(64) NOT NULL, 
+                       location VARCHAR(256) NOT NULL,
+                       CONSTRAINT fk_project_sources_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ))#{post_fix}"
+
+               db.do "CREATE TABLE packages ( 
+                       id INTEGER PRIMARY KEY #{inc}, 
+                       source_id INTEGER NOT NULL, 
+                       supported_os_id INTEGER NOT NULL, 
+                       pkg_name VARCHAR(64) NOT NULL,
+                       CONSTRAINT fk_project_packages_project_sources1 FOREIGN KEY ( source_id ) REFERENCES sources ( id ),
+                       CONSTRAINT fk_project_packages_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ) )#{post_fix}"
+
+       end
+
+
+       protected
+       def self.load_row(name, dist_name, db)
+               row = db.select_one("SELECT projects.* FROM projects,distributions WHERE projects.name='#{name}' and 
+                                                       projects.distribution_id=distributions.id and distributions.name='#{dist_name}'")
+               if row.nil? then return nil end
+
+               # get supported_os
+               prj_id = row['id']
+               os_list = []
+               rows = db.select_all("SELECT supported_os.name FROM project_os,supported_os WHERE project_id=#{prj_id} and supported_os.id = project_os.supported_os_id")
+               rows.each do |r|
+                       os_list.push r['name']
+               end
+
+               # get source info/ package info
+               source_info = {}
+               package_info = {}
+               rows=db.select_all("SELECT * FROM sources WHERE project_id=#{prj_id}")
+               rows.each do |r|
+                       source_info[r['pkg_ver']] = r['location']
+
+                       source_id = r['id']
+                       rows2=db.select_all("SELECT packages.pkg_name,supported_os.name as os_name 
+                               FROM packages,supported_os WHERE source_id=#{source_id} and packages.supported_os_id=supported_os.id")
+                       rows2.each do |r2|
+                               if package_info[r['pkg_ver']].nil? then
+                                       package_info[r['pkg_ver']] = []
+                               end
+                               package_info[r['pkg_ver']].push [r2['pkg_name'], r2['os_name']]
+                       end     
+               end
+
+               return row, os_list, source_info, package_info
+       end
+
+
+       protected
+       def save_common(db)
+               if @prj_id == -1 then
+                       row = db.select_one("SELECT * FROM distributions WHERE name='#{@dist_name}'")
+                       dist_id = row['id']
+                       db.do "INSERT INTO projects (distribution_id,name,ptype,password) 
+                               VALUES (#{dist_id},'#{@name}','#{@type}','#{@passwd}')"
+                       case @server.db_dsn
+                       when /^SQLite3:/ then @prj_id = db.select_one("select last_insert_rowid()")[0]
+                       when /^Mysql:/ then @prj_id = db.func(:insert_id)
+                       else @prj_id = db.select_one("select last_insert_rowid()")[0]
+                       end
+                       @os_list.each do |os|
+                               row = db.select_one("SELECT * FROM supported_os WHERE name='#{os}'")
+                               os_id = row['id']
+                               db.do "INSERT INTO project_os VALUES(#{@prj_id},#{os_id})"
+                       end
+
+                       return  true
+               else
+                       row = db.select_one("SELECT * FROM distributions WHERE name='#{@dist_name}'")
+                       dist_id = row['id']
+                       db.do "UPDATE projects SET ptype='#{@type}',password='#{@passwd}' WHERE name='#{@name}' and distribution_id=#{dist_id})"
+                       db.do "DELETE FROM project_os WHERE project_id=#{@prj_id}"
+                       @os_list.each do |os|
+                               row = db.select_one("SELECT * FROM supported_os WHERE name='#{os}'")
+                               os_id = row['id']
+                               db.do "INSERT INTO project_os VALUES(#{@prj_id},#{os_id})"
+                       end
+
+                       @source_info.each do |src_ver,info|
+                               save_source_info_internal(src_ver, info, db)
+                       end
+
+                       @package_info.each do |src_ver,pkg_name_os_pair|
+                               pkg_name_os_pair.each do |pkg_name, pkg_os|
+                                       save_package_info_internal(src_ver, pkg_name, pkg_os, db)
+                               end
+                       end
+
+                       return false
+               end
+       end
+
+
+       public
+       def get_source_id_from_ver( src_ver, db )
+               row=db.select_one("SELECT * FROM sources WHERE project_id=#{@prj_id} and pkg_ver='#{src_ver}'")
+               if row.nil? then 
+                       return "NULL"
+               else
+                       return row['id']
+               end
+       end
+
+
+       protected
+       def save_source_info_internal(src_ver, info, db)        
+               row1=db.select_one("SELECT * FROM sources WHERE project_id=#{@prj_id} and pkg_ver='#{src_ver}'")
+               if row1.nil? then
+                       db.do "INSERT INTO sources(project_id, pkg_ver,location) 
+                               VALUES(#{@prj_id},'#{src_ver}','#{info}')"
+               end
+       end
+
+
+       protected
+       def save_package_info_internal(src_ver, pkg_name, pkg_os, db)
+               row=db.select_one("SELECT * FROM sources WHERE project_id=#{@prj_id} and pkg_ver='#{src_ver}'")
+               source_id = row['id']
+               row = db.select_one("SELECT * FROM supported_os WHERE name='#{pkg_os}'")
+               os_id = row['id']
+               row1=db.select_one("SELECT * FROM packages WHERE source_id=#{source_id} and pkg_name='#{pkg_name}' and supported_os_id=#{os_id}")
+               if row1.nil? then
+                       db.do "INSERT INTO packages(source_id,supported_os_id,pkg_name) VALUES(#{source_id},#{os_id},'#{pkg_name}')"
+               end
+       end
+
+
+       # return its prject id and if not exist?, return -1
+       protected
+       def unload_common(db)
+               row = db.select_one("SELECT * FROM projects WHERE id=#{@prj_id}")
+               if row.nil? then return -1 end
+               db.do "DELETE FROM project_os WHERE project_id=#{@prj_id}"
+               rows=db.select_all("SELECT * FROM sources WHERE project_id=#{@prj_id}")
+               rows.each do |r|
+                       source_id = r['id']
+                       db.do "DELETE FROM packages WHERE source_id=#{source_id}"
+               end
+               db.do "DELETE FROM sources WHERE project_id=#{@prj_id}"
+               db.do("DELETE FROM projects WHERE id=#{@prj_id}")
+       end
+
+
+       public
+       def self.get_project_row(name, dist_name, db)
+               return db.select_one("SELECT * FROM projects WHERE name='#{name}' AND distribution_id=(SELECT id FROM distributions WHERE name='#{dist_name}')")
+       end
+
+       public
+       def self.get_project_from_pkg_name_row(pkg_name, dist_name, db)
+               return db.select_one("SELECT projects.id,projects.distribution_id,projects.name,projects.ptype,projects.password 
+                                                        FROM distributions,projects,project_bins
+                                                        WHERE distributions.name='#{dist_name}' and
+                                                        distributions.id = projects.distribution_id and
+                                                        projects.id = project_bins.project_id and
+                                                        project_bins.pkg_name = '#{pkg_name}'")
+       end
+
+       public
+       def self.get_all_project_rows(db)
+               return db.select_all("SELECT projects.name,distributions.name as dist_name,projects.ptype 
+                       FROM projects,distributions WHERE projects.distribution_id=distributions.id")
+       end
+end
diff --git a/src/build_server/DistributionManager.rb b/src/build_server/DistributionManager.rb
new file mode 100644 (file)
index 0000000..2550496
--- /dev/null
@@ -0,0 +1,227 @@
+=begin
+
+ DistributionManager.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__))+"/pkg_server"
+require "SocketJobRequestListener.rb"
+require "RemoteBuildJob.rb"
+require "RegisterPackageJob.rb"
+require "packageServer.rb"
+
+class PackageDistribution
+       attr_accessor :name, :pkgsvr_url, :pkgsvr_ip, :pkgsvr_port, :status, :description, :id
+
+       def initialize( name, pkgsvr_url, pkgsvr_ip, pkgsvr_port, status )
+               @id = -1
+               @name = name
+               @pkgsvr_url = pkgsvr_url
+               @pkgsvr_ip = pkgsvr_ip
+               @pkgsvr_port = pkgsvr_port
+               @status = status
+               @description = ""
+       end
+
+
+       def self.create_table(db, inc, post_fix)
+               db.do "CREATE TABLE distributions ( 
+                       id INTEGER PRIMARY KEY #{inc}, 
+                       name VARCHAR(32) NOT NULL UNIQUE, 
+                       pkgsvr_url VARCHAR(256), 
+                       pkgsvr_addr VARCHAR(64), 
+                       status VARCHAR(32) NOT NULL DEFAULT 'OPEN',
+                       description VARCHAR(256) ) #{post_fix}"
+       end
+
+
+       def self.load(name, db)
+               row = db.select_one("SELECT * FROM distributions WHERE name='#{name}'")
+               return ( row.nil? ) ? nil : load_row(row)
+       end
+
+
+       def unload(db)
+               #TODO remove sync_pkg_server
+               #TODO remove projects
+               #TODO remove jobs
+               db.do("DELETE FROM distributions WHERE name='#{@name}'")
+       end
+
+
+       def self.load_all(db)
+               rows = db.select_all("SELECT * FROM distributions")
+               return rows.map{|x| load_row(x)}
+       end
+
+
+       def self.load_first(db)
+               row = db.select_one("SELECT * FROM distributions ORDER BY id")
+               return ( row.nil? ) ? nil : load_row(row)
+       end
+
+
+       def self.load_row(row)
+               pkgsvr_ip = row['pkgsvr_addr'].split(":")[0]
+               pkgsvr_port = row['pkgsvr_addr'].split(":")[1].to_i
+               new_obj = new(row['name'], row['pkgsvr_url'], pkgsvr_ip, pkgsvr_port, row['status'])
+               new_obj.description = row['description']
+               new_obj.id = row['id']
+
+               return new_obj
+       end
+
+
+       def save(db)
+               dist_addr = @pkgsvr_ip + ":" + @pkgsvr_port.to_s
+               row = db.select_one("SELECT * FROM distributions WHERE name='#{@name}'")
+               if row.nil? then
+                       db.do "INSERT INTO distributions(name, pkgsvr_url, pkgsvr_addr, status, description) VALUES ('#{@name}','#{@pkgsvr_url}','#{dist_addr}','#{@status}','#{@description}')"
+               else
+                       db.do "UPDATE distributions SET pkgsvr_url='#{@pkgsvr_url}', pkgsvr_addr='#{dist_addr}', status='#{@status}', description='#{@description}' WHERE name='#{@name}'"
+               end
+       end
+
+
+       def self.get_distribution_id(db, dist_name)
+               row = db.select_one("SELECT * FROM distributions WHERE name='#{dist_name}'")
+               return ( row.nil? ) ? "NULL" : row['id']
+       end
+end
+
+
+class DistributionManager
+
+       # initialize
+       def initialize( server )
+               @server = server
+       end
+
+
+       # get default distribution
+       def get_default_distribution_name()
+               dist = get_first_distribution()
+               return ( dist.nil? ) ? nil : dist.name
+       end
+
+
+       def get_default_pkgsvr_url()
+               dist = get_first_distribution()
+               return ( dist.nil? ) ? "" : dist.pkgsvr_url
+       end
+
+
+       # get distribution
+       def get_distribution(name)
+               # conntect DB
+               @server.get_db_connection() do |db|
+                       return get_distribution_internal(name, db)
+               end
+               return nil
+       end
+
+
+       def get_distribution_internal(name, db)
+               return PackageDistribution.load(name, db)
+       end
+
+
+       # add
+       def add_distribution(name, pkgsvr_url, pkgsvr_ip, pkgsvr_port)
+               @server.get_db_connection() do |db|
+                       if not get_distribution_internal(name, db).nil? then
+                               @server.log.info "The distribution \"#{name}\" already exists on server"
+                               @server.log.error "Adding distribution failed!"
+                               return false
+                       end
+                       new_dist = PackageDistribution.new(name, pkgsvr_url, pkgsvr_ip, pkgsvr_port, "OPEN")
+                       new_dist.save(db)
+               end
+               @server.log.info "Added a new distribution \"#{name}\""
+               return true
+       end
+
+
+       # remove
+       def remove_distribution(name)
+
+               result = @server.get_db_connection() do |db|
+                       dist = get_distribution_internal(name, db)
+                       if dist.nil? then
+                               @server.log.error "The distribution \"#{name}\" does not exists on server"
+                               @server.log.error "Removing distribution failed!"
+                               return false
+                       end
+                       dist.unload(db)
+               end
+
+               @server.log.info "Removed the distribution \"#{name}\""
+               return result
+       end
+
+
+       def get_first_distribution()
+               @server.get_db_connection() do |db|
+                       return PackageDistribution.load_first(db)
+               end
+
+               return nil
+       end
+
+
+       def get_all_distributions()
+               @server.get_db_connection() do |db|
+                       return PackageDistribution.load_all(db)
+               end
+
+               return []
+       end
+
+
+       def set_distribution_lock(name, value=true)
+               result = @server.get_db_connection() do |db|
+                       # check already exist
+                       dist = get_distribution_internal(name, db)
+                       if dist.nil? then return false end
+
+                       dist.status = (value)? "CLOSE" : "OPEN"
+                       dist.save(db)
+               end
+               if result then
+                       if value then
+                               @server.log.info "The distribution \"#{name}\" is locked!"
+                       else
+                               @server.log.info "The distribution \"#{name}\" is unlocked!"
+                       end
+               end
+
+               return result
+       end
+
+       #END
+end
index d328925304575f88fc100577e10bb7df4180aee5..301d810ac455242ad7b51c50d0964ea6e751349f 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  GitBuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -27,194 +27,286 @@ Contributors:
 =end
 
 require "fileutils"
+require "thread"
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "BuildJob.rb"
 require "utils.rb"
 
+
+$git_mutex = Mutex.new
+
 class GitBuildJob < BuildJob
-       attr_accessor :id, :status, :pkginfo, :pkgsvr_client, :thread, :log, :rev_fail_list, :rev_success_list, :source_path
+       attr_accessor :git_commit, :git_branch, :git_repos
 
        # initialize
-       def initialize ( repos, commit, os, pkgsvr_url, options, server, parent, outstream, resolve)
-               super()
-        @rev_fail_list = []
-        @rev_success_list = []
-               @id = server.get_new_job_id()
-               @server = server
-               @parent = parent
-               @git_repos = repos
-               @git_commit = commit
-               @os = os
-               @host_os = Utils::HOST_OS
-               if not pkgsvr_url.nil? and not pkgsvr_url.empty? then
-                       @pkgserver_url = pkgsvr_url
-               else 
-                       local_pkgsvr = @server.local_pkgsvr
-                       @pkgserver_url = local_pkgsvr.location + "/" + local_pkgsvr.get_default_dist_name
-               end
-               @options = options
-        @resolve = resolve
-               @outstream = outstream
-
-               @status = "JUST_CREATED"
-               @sub_jobs = []
-               @job_root = "#{@server.path}/jobs/#{@id}"
-               @source_path = @job_root+"/temp"
-               @pkginfo = nil
-               @job_working_dir=@job_root+"/works"     
-
-               @thread = nil
-
-               # mkdir 
-               FileUtils.rm_rf "#{@server.path}/jobs/#{@id}"
-               FileUtils.mkdir_p "#{@server.path}/jobs/#{@id}"
-
-               # create logger
-               @log = JobLog.new(self,"#{@server.path}/jobs/#{@id}/log", outstream )
+       def initialize( project, os, server )
+               super(project, os, server)
+               @git_repos = project.repository
+               @git_branch = project.branch
+               @git_commit = nil
        end
 
 
        def terminate()
-
                # report error
                if @status == "ERROR" then
                        @log.error( "Job is stopped by ERROR" , Log::LV_USER)
+                       @server.cleaner.clean_afterwards(@id)
+               elsif @status == "CANCELED" then
+                       if not @log.nil? then
+                               @log.error( "Job is CANCELED" , Log::LV_USER)
+                       end
+                       @server.cleaner.clean_afterwards(@id)
                else
-                       # if succeeded, clean up
-                       FileUtils.rm_rf "#{@source_path}"
-                       FileUtils.rm_rf "#{@job_working_dir}"
+                       @log.info( "Job is FINISHED successfully!" , Log::LV_USER)
+
+                       # if succeeded, register source info and copy pkginfo.manifest
+                       @log.info( "Updating the source info for project \"#{@project.name}\"" , Log::LV_USER)
+                       @project.save_source_info( @pkginfo.get_version(), @git_commit)
+                       @project.save_package_info_from_manifest( @pkginfo.get_version(),
+                               "#{@source_path}/package/pkginfo.manifest", @os)
+                       @server.jobmgr.save_job_status(self)
+                       # clean up
+                       @server.cleaner.clean(@id)
+               end
+
+               # clean up builder directory if exist?
+               if Builder.exist? "JB#{@id}" then
+                       Builder.remove("JB#{@id}")
                end
 
-               # send mail 
-               if ( not @pkginfo.nil? ) and not ( @pkginfo.packages.nil? ) then 
+               # send mail
+               if ( @server.send_mail.eql? "YES" ) and ( not @pkginfo.nil? ) and ( not @pkginfo.packages.nil? ) then
                        mail_list = []
                        contents = []
-                       done_pkg_list = []
                        contents.push " "
                        contents.push " Git information : #{@git_commit} "
                        contents.push " "
                        contents.push "%-30s| %10s | %10s" % ["package name", "version", "os"]
                        contents.push "---------------------------------------------------------------"
-                       for pkg in @pkginfo.packages  
-                               if not pkg.os.eql? @os then next end 
-                               mail_list = mail_list | Mail.parse_email( pkg.maintainer )  
+                       @pkginfo.packages.each do |pkg|
+                               if not pkg.os.eql? @os then next end
+                               mail_list = mail_list | Mail.parse_email( pkg.maintainer )
                                contents.push("%-30s| %10s | %10s" % [ pkg.package_name, pkg.version, pkg.os] )
                        end
-                       
-                       if @status == "ERROR" then 
-                               subject = "[DIBS] Build fail" 
+
+                       if @status == "ERROR" then
+                               subject = "[DIBS] Build fail"
                                contents.push " "
                                contents.push "check log file"
                                contents.push "* Log : #{@server.job_log_url}/#{@id}/log"
+                       elsif @status == "CANCELED" then
+                               subject = "[DIBS] Build canceled"
                        else
-                               subject = "[DIBS] Build success" 
+                               subject = "[DIBS] Build success"
                        end
-                       #Mail.send_mail(mail_list, subject, contents.join("\n"))
-               end 
+                       Mail.send_mail(mail_list, subject, contents.join("\n"))
+               end
 
                # close logger
                @log.close
+       end
 
-               # send END signal , if connectionn is valid 
-               if @status != "ERROR" and not @outstream.nil? then
-                       BuildCommServer.send_end(@outstream)
-               end
 
-               # close outstream
-               if not @outstream.nil? then
-                       BuildCommServer.disconnect( @outstream )
+       # verify
+       def init
+               # mkdir job root
+               if not File.exist? @job_root then FileUtils.mkdir_p @job_root end
+
+               # create logger
+               if @log.nil? then
+                       @log = JobLog.new(self, nil )
                end
-       end
 
+               @log.info( "Initializing job...", Log::LV_USER)
 
-       # verify
-       def pre_verify
-               @log.info( "Verifying job input...", Log::LV_USER)
+               # if internal job, copy external_pkgs
+               if @is_internal_job then
+                       @log.info( "Copying external dependent pkgs...", Log::LV_USER)
+                       ext_pkgs_dir = "#{@job_root}/external_pkgs"
+
+                       incoming_dir = "#{@server.transport_path}/#{@dock_num}"
+                       if File.exist? incoming_dir then
+                               FileUtils.mv "#{incoming_dir}", "#{ext_pkgs_dir}"
+                       end
+
+                       FileUtils.mkdir_p incoming_dir
+               end
 
-               # git clone
-               if not git_cmd("clone #{@server.git_server_url}#{@git_repos} temp", @job_root) then
-                       @log.error( "Failed on \"git clone #{@server.git_server_url}/#{@git_repos}\"", Log::LV_USER)
+               # download source code
+               @git_commit = get_source_code()
+               if @git_commit.nil? then
                        @status = "ERROR"
                        return false
                end
 
-               # git reset
-               if not git_cmd("reset --hard #{@git_commit}", @source_path) then
-                       @log.error( "Failed on \"git reset --hard #{@git_commit}\"", Log::LV_USER)
+               # check pkginfo.manifest
+               if not File.exist? "#{@source_path}/package/pkginfo.manifest"
+                       @log.error( "package/pkginfo.manifest does not exist", Log::LV_USER)
                        @status = "ERROR"
                        return false
                end
 
-               # check branch name if ALLOWED_GIT_BRANCH is not empty
-               if not @server.allowed_git_branch.empty? then
-                       is_correct_branch = false
-
-                       # origin/{branch_name}
-                       if @git_commit == "origin/#{@server.allowed_git_branch}" then
-                               is_correct_branch = true
-                       else    
-                               # get commit id
-                               commit_id = ""
-                               result_line = git_cmd_return("log -1",@source_path)
-                               if result_line != nil then
-                                       result_line.each do |l|
-                                               if l.start_with?("commit ") then
-                                                       commit_id = l.split(" ")[1].strip       
-                                               end
-                                       end
-                               end
-       
-                               # check branch
-                               if not commit_id.empty? and commit_id.length == 40 then
-                                       result_line = git_cmd_return("branch --contains=#{commit_id} -r", @source_path)
-                                       result_line.each do |l|
-                                               if l.include? "origin/#{@server.allowed_git_branch}" then
-                                                       is_correct_branch = true
-                                               end
-                                       end
-                               end
+               # set up pkg info
+               begin
+                       @pkginfo = PackageManifest.new("#{@source_path}/package/pkginfo.manifest")
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       return false
+               end
+
+               # set up pkgsvr_client
+               @pkgsvr_client =  Client.new(@pkgsvr_url, @job_working_dir, @log)
+
+               # checking version if not reverse-build job or not internal-job
+               if not @is_rev_build_check_job and not @is_internal_job  then
+
+                       #check change log
+                       change_log = {}
+                       begin
+                               change_log = Parser.read_changelog "#{@source_path}/package/changelog" if File.exist? "#{@source_path}/package/changelog"
+                       rescue => e
+                               @log.error( e.message, Log::LV_USER)
+                               return false
                        end
 
-                       if not is_correct_branch then
-                               @log.error( "Wrong branch is used! Check your commit-id again", Log::LV_USER)
+                       if not change_log.empty? and @pkginfo.packages[0].change_log.empty? then
+                               @pkginfo.packages.each {|pkg| pkg.change_log = change_log}
+                       end
+
+                       if @server.changelog_check and not @pkginfo.packages[0].does_change_exist? then
+                               @log.error( "change log not found", Log::LV_USER )
+                               return false
+                       end
+
+                       # check availabiltiy
+                       if not @server.check_job_availability( self ) then
+                               @log.error( "No servers that are able to build your packages.", Log::LV_USER)
+                               @log.error( "Host-OS (#{@os}) is not supported in build server.", Log::LV_USER)
+                               @status = "ERROR"
+                               @server.log.info "Adding the job \"#{@id}\" is canceled"
+                               return false
+                       end
+
+                       if not check_package_version(@git_commit) then
                                @status = "ERROR"
                                return false
                        end
                end
-               
 
-               # check pkginfo.manifest
-               if not File.exist? "#{@source_path}/package/pkginfo.manifest"
-                       @log.error( "package/pkginfo.manifest doest not exist", Log::LV_USER)
-                       @status = "ERROR"
-                       return false
+               return true
+       end
+
+
+       #
+       # PROTECTED/PRIVATE METHODS
+       #
+
+       protected
+       def get_source_code()
+               $git_mutex.synchronize do
+                       get_source_code_internal()
                end
+       end
 
-               # set up pkg info
-               @pkginfo = PackageManifest.new("#{@source_path}/package/pkginfo.manifest")
 
-               # set up pkgsvr_client
-               @pkgsvr_client =  Client.new(@pkgserver_url, @job_working_dir, @log)
-               @pkgsvr_client.update
+       protected
+       def get_source_code_internal()
+               # check git directory
+               git_path = "#{@project.path}/cache/git"
+               cache_path = "#{@project.path}/cache"
+               if not File.exist? cache_path then
+                       FileUtils.mkdir_p cache_path
+               end
 
-               return true
+               # verify git & check branch name
+               if File.exist? git_path then
+                       std_out_lines = git_cmd_return( "branch",  git_path)
+                       if std_out_lines.nil? then 
+                               @log.warn( "Git cache is corrupted! : #{@project.name}", Log::LV_USER)
+                               FileUtils.rm_rf git_path
+                       else
+                               branch_list = std_out_lines.select{|x| x.start_with?("*")}
+                               if branch_list.count == 0 then
+                                       @log.warn( "Git cache is corrupted! : #{@project.name}", Log::LV_USER)
+                                       FileUtils.rm_rf git_path
+                               else
+                                       current_branch = branch_list[0].split(" ")[1].strip
+                                       if current_branch != @git_branch then
+                                               @log.warn( "Branch name is changed.", Log::LV_USER)
+                                               FileUtils.rm_rf git_path
+                                       end
+                               end
+                       end
+               end
+
+               # git pull operation
+               if File.exist? git_path and not git_cmd("pull", git_path,@log) then
+                       @log.warn( "Failed on \"git pull\"", Log::LV_USER)
+                       FileUtils.rm_rf git_path
+               end
+
+               # if no git, clone it
+               if  not File.exist? git_path then
+                       # if "git pull" failed, try to "git clone"
+                       if not git_cmd("clone #{@git_repos} git", cache_path, @log) then
+                               @log.error( "Failed on \"git clone #{@git_repos}\"", Log::LV_USER)
+                               return nil
+                       end
+                       # git checkout
+                       if not git_cmd("checkout #{@git_branch}", git_path, @log) then
+                               @log.error( "Failed on \"git checkout #{@git_branch}\"", Log::LV_USER)
+                               return nil
+                       end
+               end
+
+               if @git_commit.nil? then
+                       # get git commit-id
+                       commit_id = ""
+                       result_line = git_cmd_return("log -1", git_path)
+                       if result_line != nil then
+                               result_line.each do |l|
+                                       if l.start_with?("commit ") then
+                                               commit_id = l.split(" ")[1].strip
+                                       end
+                               end
+                       end
+
+                       @git_commit = commit_id
+               else
+                       # git reset
+                       if not git_cmd("reset --hard #{@git_commit}", git_path, @log) then
+                               @log.error( "Failed on \"git reset --hard #{@git_commit}\"", Log::LV_USER)
+                               return nil
+                       end
+               end
+
+               # copy to source path
+               Utils.execute_shell_return( "cp -r #{git_path} #{@source_path}" )
+
+               return @git_commit
        end
 
 
-    def git_cmd(cmd, working_dir)
-        build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}"
-               ret = Utils.execute_shell_with_log(build_command,@log)
-               
-               return ret
+       protected
+       def git_cmd(cmd, working_dir, log)
+               build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}"
+
+               pid, status = execute_command( build_command )
+               if not status.nil? and status.exitstatus != 0 then
+                       return false
+               else
+                       return true
+               end
        end
 
 
-    def git_cmd_return(cmd, working_dir)
-        build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}"
+       protected
+       def git_cmd_return(cmd, working_dir)
+               build_command = "cd \"#{working_dir}\";#{@server.git_bin_path} #{cmd}"
                ret = Utils.execute_shell_return(build_command)
-               
+
                return ret
        end
-
 end
diff --git a/src/build_server/GitBuildProject.rb b/src/build_server/GitBuildProject.rb
new file mode 100644 (file)
index 0000000..589651b
--- /dev/null
@@ -0,0 +1,154 @@
+=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 'dbi'
+$LOAD_PATH.unshift File.dirname(__FILE__)
+require "CommonProject.rb"
+require "GitBuildJob.rb"
+require "Version.rb"
+require "PackageManifest.rb"
+
+# mutax for git operation
+
+
+class GitBuildProject < CommonProject
+       attr_accessor :repository, :branch
+
+       # initialize
+       def initialize( name, server, os_list, dist_name, repos = nil, branch = nil )
+               super(name, "GIT", server, os_list, dist_name)
+               @repository = repos
+               @branch = branch
+       end
+
+
+       # get commid-id of specified package version
+       def get_commit_id( version )
+               return get_source_info( version )
+       end
+
+
+       # create new job
+       # if this project cannot support os, return nil
+       def create_new_job( os )
+               if @os_list.include? os then
+                       return GitBuildJob.new( self, os, @server )
+               else
+                       return nil
+               end
+       end
+
+
+       # create new job
+       def create_new_job_from_version( os, version=nil )
+               new_job=create_new_job( os )
+
+               # set commit id
+               if version.nil? then
+                       version = get_latest_version()
+               end
+
+               commit = get_commit_id( version )
+               if not commit.nil? then
+                       new_job.git_commit = commit
+               end
+
+               return new_job
+       end
+
+
+       # save package info
+       def save_package_info_from_manifest(version, file_path, os)
+               begin
+                       pkginfo =PackageManifest.new(file_path)
+               rescue => e
+                       @server.log.error e.message
+                       return
+               end
+
+               pkginfo.get_target_packages(os).each do |pkg|
+                       save_package_info(pkg.version, pkg.package_name, os)
+               end
+       end
+
+
+       def self.create_table(db, post_fix)
+               db.do "CREATE TABLE project_gits ( 
+                       project_id INTEGER NOT NULL, 
+                       git_repos VARCHAR(128) NOT NULL, 
+                       git_branch VARCHAR(32) NOT NULL,
+                       PRIMARY KEY ( project_id ),
+                       CONSTRAINT fk_project_gits_projects1 FOREIGN KEY ( project_id ) REFERENCES projects ( id ) )#{post_fix}"
+       end
+
+
+       def self.load(name, dist_name, server, db)
+               row, prj_os_list, source_info, package_info = load_row(name, dist_name, db)
+               if row.nil? then return nil end
+
+               prj_id = row['id']
+               prj_name = row['name']
+               prj_passwd = row['password']
+
+               new_project = GitBuildProject.new(prj_name, server, prj_os_list, dist_name)
+               if not prj_passwd.empty? then new_project.passwd = prj_passwd end
+               new_project.set_project_id( prj_id )
+               new_project.set_source_info( source_info )
+               new_project.set_package_info( package_info )
+
+               row=db.select_one("SELECT * FROM project_gits WHERE project_id=#{prj_id}")
+               if row.nil? then return nil end
+               new_project.repository=row['git_repos']
+               new_project.branch=row['git_branch']
+
+               return new_project
+       end
+
+       
+       def save(db)
+               is_new = save_common(db)
+               init()
+
+               if is_new then
+                       db.do "INSERT INTO project_gits VALUES (#{@prj_id},'#{@repository}','#{@branch}')"
+                       db.do "INSERT INTO group_project_accesses 
+                               VALUES ( (SELECT groups.id FROM groups WHERE groups.name = 'admin'),'#{@prj_id}','TRUE')"
+               else
+                       db.do "UPDATE project_gits SET git_repos='#{@repository}',git_branch='#{@branch}' WHERE project_id=#{@prj_id})"
+               end
+       end
+
+
+       def unload(db)
+               unload_common(db)
+               if @prj_id != -1 then
+                       db.do "DELETE FROM project_gits WHERE project_id=#{@prj_id}"
+               end
+       end
+end
diff --git a/src/build_server/JobClean.rb b/src/build_server/JobClean.rb
new file mode 100644 (file)
index 0000000..54d8597
--- /dev/null
@@ -0,0 +1,199 @@
+=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 "Action.rb"
+require "ScheduledActionHandler.rb"
+
+$access_listfile = Mutex.new
+
+class JobCleanAction < Action
+
+       def initialize( time, job_path, list_file, server )
+               super(time,0)
+
+               @job_path = job_path
+               @job_id = @job_path.split("/")[-1]
+               @list_file = list_file
+               @server = server
+       end
+
+
+       def init
+               $access_listfile.synchronize do
+                       File.open(@list_file, "a") do |f|
+                               f.puts "#{@job_id},#{time.year},#{time.month},#{time.day},#{time.hour},#{time.min},#{time.sec}"
+                       end
+               end
+       end
+
+
+       def execute
+               # Start to clean job
+               @server.log.info "Executing clean action for the job #{@job_id}"
+               begin
+                       execute_internal()
+               rescue => e
+                       @server.log.error e.message
+                       @server.log.error e.backtrace.inspect
+               end
+       end
+
+
+       private
+       def execute_internal()
+               # remove directories
+               if File.exist? "#{@job_path}/buildroot" then
+                       FileUtils.rm_rf "#{@job_path}/buildroot"
+               end
+               if File.exist? "#{@job_path}/temp" then
+                       FileUtils.rm_rf "#{@job_path}/temp"
+               end
+               if File.exist? "#{@job_path}/external_pkgs" then
+                       FileUtils.rm_rf "#{@job_path}/external_pkgs"
+               end
+
+               # remove line for the job
+               $access_listfile.synchronize do
+                       lines = []
+                       # get all lines
+                       if File.exist? @list_file then
+                               File.open(@list_file,"r") do |f|
+                                       f.each_line do |l|
+                                               lines.push l
+                                       end
+                               end
+                       end
+
+                       # write the line except my job_id
+                       File.open(@list_file,"w") do |f|
+                               lines.each do |l|
+                                       if l.split(",")[0].eql? @job_id then next end
+                                       f.puts l
+                               end
+                       end
+               end
+       end
+end
+
+
+class JobCleaner
+       attr_accessor :quit
+
+       # init
+       def initialize( server )
+               @server = server
+               @handler = ScheduledActionHandler.new
+               @list_file = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/clean"
+       end
+
+
+       # start thread
+       def start()
+
+               list_file2 = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/clean_backup"
+               jobs_path = "#{@server.path}/jobs"
+               if not File.exist? jobs_path then
+                       FileUtils.mkdir_p jobs_path
+               end
+
+               # read clean list
+               clean_list = []
+               if File.exist? @list_file then
+                       FileUtils.mv(@list_file,list_file2)
+                       File.open(list_file2, "r") do |f|
+                               f.each_line do |l|
+                                       id = l.split(",")[0]
+                                       year = l.split(",")[1]
+                                       month = l.split(",")[2]
+                                       day = l.split(",")[3]
+                                       hour = l.split(",")[4]
+                                       min = l.split(",")[5]
+                                       sec = l.split(",")[6]
+
+                                       # create job and register
+                                       job_path = "#{jobs_path}/#{id}"
+                                       time = Time.mktime(year.to_i, month.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i)
+                                       @server.log.info "Registered clean-action for the job in list : #{id}"
+                                       @handler.register(JobCleanAction.new(time,job_path,@list_file, @server))
+
+                                       # add clean list
+                                       clean_list.push id
+                               end
+                       end
+               end
+
+
+               # scan all jobs
+               Dir.new(jobs_path).entries.each do |id|
+                       # skip . or ..
+                       if id.eql? "." or id.eql? ".." then next end
+
+                       # remove directory if jobs directory is created too long ago
+                       job_path = "#{jobs_path}/#{id}"
+                       dir_keep_time = 86400 < @server.keep_time ? @server.keep_time : 86400
+                       if File.ctime(job_path) + dir_keep_time < Time.now then
+                               FileUtils.rm_rf job_path
+                               @server.log.info "Removed the job directory: #{id}"
+                               next
+                       end
+
+                       if not clean_list.include? id then
+                               time = Time.now
+                               @server.log.info "Registered clean-action for old job : #{id}"
+                               @handler.register(JobCleanAction.new(time,job_path,@list_file, @server))
+                       end
+               end
+
+               # start handler
+               @handler.start
+       end
+
+
+       # clean after some time
+       def clean_afterwards(job_id)
+               time = Time.now + @server.keep_time
+               job_path = "#{@server.path}/jobs/#{job_id}"
+               @handler.register(JobCleanAction.new(time, job_path, @list_file, @server))
+
+               @server.log.info "Registered delayed clean-action for the job #{job_id}"
+       end
+
+
+       # clean directly
+       def clean(job_id)
+               time = Time.now
+               job_path = "#{@server.path}/jobs/#{job_id}"
+               @handler.register(JobCleanAction.new(time, job_path, @list_file, @server))
+
+               @server.log.info "Registered clean-action for the job #{job_id}"
+       end
+end
index c46db4855c9a919c3b544e9f8abcdb4c3fb2779c..def805604fbe77dbb2ef33189951755ce0d06d26 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- JobLog.rb 
+
+ JobLog.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -34,37 +34,80 @@ require "BuildComm.rb"
 
 class JobLog < Log
 
-       def initialize(job, path, stream_out)
-               super(path)
+       def initialize(job, stream_out, verbose = false)
+               log_level = (verbose) ?  Log::LV_NORMAL : Log::LV_USER
+               if job.nil? then
+                       super(nil)
+               else
+                       if not File.exist? "#{job.server.path}/jobs/#{job.id}" then
+                               FileUtils.mkdir_p "#{job.server.path}/jobs/#{job.id}"
+                       end
+                       super("#{job.server.path}/jobs/#{job.id}/log",log_level)
+               end
                @parent_job=job
                @second_out = stream_out
        end
 
 
+       def set_second_out( out )
+               @second_out = out
+       end
+
+
+       def close
+               # close communication
+               if not @second_out.nil? then
+                       begin
+                               if  not @second_out.closed? then
+                                       BuildCommServer.send_end(@second_out)
+                               end
+                       rescue
+                       end
+                       BuildCommServer.disconnect(@second_out)
+               end
+
+               @second_out = nil
+       end
+
+
+       def is_connected?
+               if @second_out.nil? or @second_out.closed? then
+                       return false
+               else
+                       return true
+               end
+       end
+
+
+       def has_second_out?
+               if @second_out.nil? then
+                       return false
+               else
+                       return true
+               end
+       end
+
+
        protected
 
        # overide
        def output_extra(msg)
-               begin 
+               begin
                        if not @second_out.nil? then
                                BuildCommServer.send( @second_out, msg )
                        end
                rescue
-                       @parent_job.status="ERROR"
-                       close()
-                       error "Connection closed by remote client"
+                       # close second_out
+                       @second_out.close
+                       @second_out = nil
 
-                       # terminate job
-                       @parent_job.terminate
+                       error "Connection closed by remote client"
 
-                       # exit thread if independent worker thread
-                       if @parent_job.thread == Thread.current then
-                               error "Thread wiil be terminated"
-                               @parent_job.thread=nil
-                               Thread.exit
+                       # cancel parent job
+                       if not @parent_job.nil? and @parent_job.cancel_state == "NONE" then
+                               @parent_job.cancel_state = "INIT"
                        end
                end
-       end     
-
+       end
 
 end
diff --git a/src/build_server/JobManager.rb b/src/build_server/JobManager.rb
new file mode 100644 (file)
index 0000000..dc6dbae
--- /dev/null
@@ -0,0 +1,589 @@
+=begin
+
+ JobManager.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__))+"/pkg_server"
+require "SocketJobRequestListener.rb"
+require "RemoteBuildJob.rb"
+require "RegisterPackageJob.rb"
+require "packageServer.rb"
+
+
+class JobManager
+       attr_accessor :jobs, :internal_jobs, :reverse_build_jobs
+       attr_accessor :internal_job_schedule
+
+       # initialize
+       def initialize( parent )
+               @server = parent
+               @jobs = []
+               @internal_jobs = []
+               @reverse_build_jobs = []
+               @new_job_index = 0
+               @internal_job_schedule = Mutex.new
+               @latest_job_touch = Mutex.new
+       end
+
+       def cancel_broken_status
+               @server.get_db_connection() do |db|
+                       db.do "UPDATE jobs SET status = 'CANCELED' WHERE status != 'FINISHED' and status != 'ERROR' and status != 'CANCELED'"
+               end
+       end
+
+       def max_working_jobs
+               result = nil
+               @server.get_db_connection() do |db|
+                       result = db.select_one("SELECT value FROM server_configs WHERE property = 'max_working_jobs'")[0]
+               end
+               return (result.nil?) ? 2 : result.to_i
+       end
+
+       def max_working_jobs=(job_cnt)
+               @server.get_db_connection() do |db|
+                       db.do "UPDATE server_configs SET value = '#{job_cnt}' WHERE property = 'max_working_jobs'"
+               end
+       end
+
+       # initialize
+       def init()
+               # load latest job idx if exist
+               file_path = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/latest_job"
+               if File.exist? file_path then
+                       latest_idx = -1
+                       File.open( file_path, "r" ) do |f|
+                               f.each_line do |l|
+                                       latest_idx = l.strip.to_i
+                                       break
+                               end
+                       end
+                       if latest_idx < 0 then latest_idx = -1 end
+                       @new_job_index = latest_idx + 1
+               else
+                       @new_job_index = 0
+               end
+       end
+
+
+       # get new id
+       def get_new_job_id
+               new_idx = 0
+               @latest_job_touch.synchronize do
+                       new_idx = @new_job_index
+
+                       file_path = "#{BuildServer::CONFIG_ROOT}/#{@server.id}/latest_job"
+                       File.open( file_path, "w" ) do |f|
+                               f.puts "#{@new_job_index}"
+                       end
+
+                       @new_job_index += 1
+               end
+
+               return new_idx
+       end
+
+       def is_user_accessable(job,user_id)
+               if job.type == "MULTIBUILD" then
+                       job.get_sub_jobs().each do |subjob|
+                               if is_user_accessable(subjob,user_id) then
+                                       return true
+                               end
+                       end
+               else
+                       result = nil
+                       @server.get_db_connection() do |db|
+                               result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses
+                                       WHERE user_groups.group_id = group_project_accesses.group_id and
+                                       group_project_accesses.project_id = #{job.get_project.get_project_id} and
+                                       user_groups.user_id = #{user_id}"
+                       end
+                       return (not result.nil?)
+               end
+               return false
+       end
+
+       def create_new_register_job( file_path, dist_name )
+               return RegisterPackageJob.new( file_path, nil, @server, nil, dist_name )
+       end
+
+       def set_remote(job, rserver)
+               job.set_remote_job(rserver)
+               @server.get_db_connection() do |db|
+                       db.do "UPDATE jobs SET remote_build_server_id = '#{rserver.id}' WHERE id = '#{job.id}'"
+               end
+       end
+
+       # add a normal job
+       def add_job ( new_job )
+               @server.log.info "Added new job \"#{new_job.id}\""
+               save_job_status(new_job)
+               @jobs.push( new_job )
+       end
+
+       # add internal job for multi-build job
+       def add_internal_job( new_job )
+               @server.log.info "Added new job \"#{new_job.id}\""
+               save_job_status(new_job)
+               @internal_jobs.push( new_job )
+       end
+
+       # add reverse build chek job
+       def add_reverse_build_job( new_job )
+               @server.log.info "Added new job \"#{new_job.id}\""
+               save_job_status(new_job)
+               @reverse_build_jobs.push( new_job )
+       end
+
+       # stop internal job selection
+       def stop_internal_job_schedule()
+               @internal_job_schedule.lock
+       end
+
+
+       # start internal job selection
+       def resume_internal_job_schedule()
+               @internal_job_schedule.unlock
+       end
+
+       # intialize normal job
+       def initialize_job ( job )
+               job.status = "INITIALIZING"
+               job.thread = Thread.new do
+                       save_job_status(job)
+                       begin
+                               # init
+                               if not job.init or job.status == "ERROR" then
+                                       if job.cancel_state == "NONE" then job.status = "ERROR" end
+                                       @server.log.info "Adding the job \"#{job.id}\" is canceled"
+                                       job.terminate()
+                                       save_job_status(job)
+                                       Thread.current.exit
+                               end
+                               if job.status != "FINISHED" then
+                                       job.status = "WAITING"
+                                       save_job_status(job)
+                               end
+                               @server.log.info "Checking the job \"#{job.id}\" was finished!"
+                       rescue => e
+                               @server.log.error e.message
+                               @server.log.error e.backtrace.inspect
+                       ensure
+                               job.thread = nil
+                       end
+               end
+               @server.log.info "Job \"#{job.id}\" entered INITIALIZING status"
+       end
+
+
+       #execute
+       def execute(job)
+               job.status = "WORKING"
+               save_job_status(job)
+
+               # start build
+               job.execute
+               @server.log.info "Moved the job \"#{job.id}\" to working job list"
+       end
+
+
+       # execute remote
+       def execute_remote(job, rserver)
+
+               # start build
+               set_remote(job, rserver)
+               if job.execute() then
+                       # status change & job control
+                       job.status = "REMOTE_WORKING"
+                       save_job_status(job)
+                       @server.log.info "Moved the job \"#{job.id}\" to remote job list"
+               else
+                       @server.log.info "Moving the job \"#{job.id}\" to remote failed"
+               end
+       end
+
+       def cancel_job( job)
+               job.cancel_state = "WORKING"
+               @server.log.info "Creating thread for canceling the job \"#{job.id}\""
+               Thread.new do
+                       begin
+                               #terminate job thread
+                               if not job.thread.nil? then
+                                       job.thread.terminate
+                                       job.thread = nil
+                               end
+
+                               # job cacncel
+                               job.cancel
+
+                               # cancel finished
+                               job.status = "CANCELED"
+                               save_job_status(job)
+
+                               # call terminate process for job
+                               job.terminate
+                       rescue => e
+                               @server.log.error e.message
+                               @server.log.error e.backtrace.inspect
+                       end
+               end
+       end
+
+       # handle
+       def handle()
+               # for cancel jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).select {|j| j.cancel_state == "INIT" }.each do |job|
+                       cancel_job( job )
+               end
+
+               # for reverse build jobs
+               job_list = @reverse_build_jobs
+               job_list.each do |job|
+                       # if "ERROR", "FINISHED", "CANCELED" remove it from list
+                       if job.status == "ERROR"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is stopped by ERROR"
+                               @reverse_build_jobs.delete job
+                       elsif job.status == "FINISHED"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is removed by FINISH status"
+                               @reverse_build_jobs.delete job
+                       elsif job.status == "CANCELED"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is removed by CANCELED status"
+                               @reverse_build_jobs.delete job
+                       end
+
+                       # if "JUST_CREATED", initialize it
+                       if job.status == "JUST_CREATED" then
+                               initialize_job( job )
+                       end
+               end
+
+               # for internal jobs
+               job_list = @internal_jobs
+               job_list.each do |job|
+                       # if "ERROR", "FINISHED", "CANCELED" remove it from list
+                       if job.status == "ERROR"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is stopped by ERROR"
+                               @internal_jobs.delete job
+                       elsif job.status == "FINISHED"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is removed by FINISH status"
+                               @internal_jobs.delete job
+                       elsif job.status == "CANCELED"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is removed by CANCELED status"
+                               @internal_jobs.delete job
+                       end
+
+                       # if "JUST_CREATED", initialize it
+                       if job.status == "JUST_CREATED" then
+                               initialize_job( job )
+                       end
+               end
+
+               # for normal job
+               job_list = @jobs
+               job_list.each do |job|
+                       # if "ERROR", "FINISHED", "CANCELED" remove it from list
+                       if job.status == "ERROR"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is stopped by ERROR"
+                               @jobs.delete job
+                       elsif job.status == "FINISHED"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is removed by FINISH status"
+                               @jobs.delete job
+                       elsif job.status == "CANCELED"
+                               save_job_status(job)
+                               @server.log.info "Job \"#{job.id}\" is removed by CANCELED status"
+                               @jobs.delete job
+                       end
+
+                       # if "JUST_CREATED", initialize it
+                       if job.status == "JUST_CREATED" then
+                               initialize_job( job )
+                       end
+
+                       # check the connection if job is not asynchronous job
+                       if ( job.status == "WAITING" or job.status == "REMOTE_WORKING" or job.status == "PENDING") and
+                               not job.is_asynchronous_job? and
+                               not job.is_connected? then
+
+                               job.status = "ERROR"
+                               save_job_status(job)
+                               @jobs.delete( job )
+                               @server.log.info "Job \"#{job.id}\" is disconnected by user. Removed!"
+                       end
+               end
+
+               # reverse build job ->  internal job -> normal job
+               job = get_available_job
+
+               # available job not exist?, continue
+               if not job.nil? then
+                       # oherwise, check remote server
+                       rserver = @server.get_available_server( job )
+                       if rserver != nil and rserver == @server then
+                               execute(job)
+                       elsif rserver != nil  then
+                               execute_remote(job, rserver)
+                       else
+                               #puts "No available server"
+                       end
+               end
+
+       end
+
+
+       # select the job whith no build-dependency problem
+       def get_available_job
+               # select reverse build job with round-robin method
+               selected_job = nil
+               @reverse_build_jobs.each do |job|
+                       if job.status == "WAITING" then
+                               selected_job = job
+                               break
+                       end
+               end
+               # rotate array
+               if @reverse_build_jobs.count > 0 then
+                       @reverse_build_jobs.push @reverse_build_jobs.shift
+               end
+               if not selected_job.nil? then return selected_job end
+
+               # if no reverse build job exist!
+               @internal_job_schedule.synchronize do
+                       # internal job first
+                       ret = nil
+                       if @internal_jobs.count > 0 then
+                               ret = get_available_job_in_list(@internal_jobs, true)
+                       end
+
+                       # not found, select normal job
+                       if ret.nil? then
+                               ret = get_available_job_in_list(@jobs, false)
+                       end
+
+                       return ret
+               end
+       end
+
+
+       # return "max_working_jobs_cnt - current_working_jobs_cnt"
+       def get_number_of_empty_room
+               working_cnt = 0
+               parent_list = []
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
+                       if job.status == "WORKING" then
+                               working_cnt = working_cnt + 1
+                       end
+
+                       # must exclude parent job
+                       if not job.get_parent_job().nil?  then
+                               parent_list.push job.get_parent_job()
+                       end
+               end
+
+               parent_list.uniq!
+
+               return max_working_jobs - working_cnt + parent_list.count
+       end
+
+
+       # check there are working jobs
+       def has_working_jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
+                       if job.status == "WORKING" then
+                               return true
+                       end
+               end
+
+               return false
+       end
+
+
+       # check there are waiting jobs
+       def has_waiting_jobs
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
+                       if job.status == "WAITING" then
+                               return true
+                       end
+               end
+
+               return false
+       end
+
+
+       def get_working_jobs
+               result = []
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
+                       if job.status == "WORKING" then
+                               result.push job
+                       end
+               end
+
+               return result
+       end
+
+
+       def get_waiting_jobs
+               result = []
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
+                       if job.status == "WAITING" then
+                               result.push job
+                       end
+               end
+
+               return result
+       end
+
+
+       def get_remote_jobs
+               result = []
+               (@jobs + @internal_jobs + @reverse_build_jobs).each do |job|
+                       if job.status == "REMOTE_WORKING" then
+                               result.push job
+                       end
+               end
+
+               return result
+       end
+
+
+       def get_pending_jobs
+               result = []
+               @jobs.each do |job|
+                       if job.status == "PENDING" then
+                               result.push job
+                       end
+               end
+
+               return result
+       end
+
+       def save_job_status(job)
+               now = @server.db_now
+               result = @server.get_db_connection() do |db|
+                       job.save(db, now)
+               end
+
+               return result
+       end
+
+
+       protected
+       # select the job whith no build-dependency problem
+       # if "check_dep_wait" is true, it will check the build dependency
+       # among items of "WAIT" status in list
+       def get_available_job_in_list( jobs, check_dep_wait=false )
+
+               # gather all working jobs and full-build jobs
+               check_dep_jobs = []
+               jobs.each do |job|
+                       if job.cancel_state != "NONE" then next end
+
+                       if job.status == "WORKING" or job.status == "REMOTE_WORKING" or job.status == "PENDING" then
+                               check_dep_jobs.push job
+                       elsif ( check_dep_wait and job.status == "WAITING") then
+                               check_dep_jobs.push job
+                       end
+               end
+
+               # get candidates for waiting jobs
+               candidate_jobs = []
+               jobs.each do |job|
+                       if job.cancel_state != "NONE" then next end
+                       if job.status != "WAITING" then next end
+
+                       # check build dependency against working job
+                       pre_jobs = []
+                       check_dep_jobs.each do |cjob|
+                               if job == cjob then next end
+                               # In case that "WORKING/REMOTE_WORKING" job has build dependency on me
+                               if (cjob.status == "WORKING" or cjob.status == "REMOTE_WORKING" ) and
+                                       (job.has_build_dependency?( cjob ) or job.is_compatible_with?( cjob)) then
+                                       pre_jobs.push cjob
+                                       # In case that "PENDING" job is depends on me (not depended )
+                               elsif cjob.status == "PENDING"  and (not job.does_depend_on? cjob) and
+                                       (job.has_build_dependency?( cjob ) or job.is_compatible_with?( cjob)) then
+                                       pre_jobs.push cjob
+                               elsif check_dep_wait and cjob.status == "WAITING" and
+                                       (job.does_depend_on? cjob or
+                                        (job.id > cjob.id and job.is_compatible_with? cjob) ) then
+                                       pre_jobs.push cjob
+                               end
+                       end
+
+                       # check pre-requisite  jobs are changed, notify to user
+                       is_changed = false
+                       if pre_jobs.count != job.pre_jobs.count then
+                               is_changed=true
+                       else
+                               pre_jobs.each do |pjob|
+                                       if not  job.pre_jobs.include? pjob then
+                                               is_changed = true
+                                               break
+                                       end
+                               end
+                       end
+                       if pre_jobs.count > 0 and is_changed then
+                               job.log.info( "Waiting for finishing following jobs:", Log::LV_USER)
+                               pre_jobs.each do |bjob|
+                                       if bjob.type == "BUILD" then
+                                               job.log.info( " * #{bjob.id} #{bjob.pkginfo.packages[0].source}", Log::LV_USER)
+                                       elsif bjob.type == "MULTIBUILD" then
+                                               job.log.info( " * #{bjob.id} (Multi Build Job)", Log::LV_USER)
+                                       end
+                               end
+                       end
+                       job.pre_jobs = pre_jobs
+
+                       # no pre-requisite jobs, return its job
+                       if job.pre_jobs.count == 0  then
+                               candidate_jobs.push job
+                       end
+               end
+
+               # select a job by priority
+               if candidate_jobs.count == 0 then return nil end
+               max_priority = -1
+               max_priority_job = nil
+               candidate_jobs.each do |job|
+                       if max_priority < job.priority then
+                               max_priority = job.priority 
+                               max_priority_job = job
+                       end
+               end
+
+               return max_priority_job 
+       end
+
+end
diff --git a/src/build_server/MultiBuildJob.rb b/src/build_server/MultiBuildJob.rb
new file mode 100644 (file)
index 0000000..5e5d98e
--- /dev/null
@@ -0,0 +1,456 @@
+=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 "JobLog.rb"
+require "mail.rb"
+require "CommonJob.rb"
+
+class MultiBuildJob < CommonJob
+
+       attr_accessor :source_path, :cancel_state
+       attr_accessor :pkgsvr_client, :thread
+
+       # initialize
+       def initialize (server)
+               super(server)
+               @log = nil
+               @type = "MULTIBUILD"
+
+               @host_os = Utils::HOST_OS
+               @pkgsvr_url = nil
+               @pkgsvr_ip = nil
+               @pkgsvr_port = nil
+               @job_root = "#{@server.path}/jobs/#{@id}"
+               @source_path = @job_root+"/temp"
+               @job_working_dir=@job_root+"/works"
+               @buildroot_dir = "#{@job_root}/buildroot"
+               @cancel_state = "NONE"
+
+       end
+
+
+       def get_distribution_name()
+               return @sub_jobs[0].get_project().dist_name
+       end
+
+
+       def get_buildroot()
+               return @buildroot_dir
+       end
+
+
+       def is_rev_build_check_job()
+               return false
+       end
+
+       def set_no_reverse()
+               @sub_jobs.each do |sub|
+                       sub.no_reverse = true
+               end
+       end
+
+       # cnacel
+       def cancel()
+               @sub_jobs.select{|x| x.cancel_state == "NONE"}.each do |sub|
+                       sub.cancel_state = "INIT"
+               end
+               if not @log.nil? then
+                       @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER)
+               end
+       end
+
+       #
+       def init
+               # mkdir
+               if not File.exist? @job_root then
+                       FileUtils.mkdir_p @job_root
+               end
+
+               # create logger
+               if @log.nil? then
+                       @log = JobLog.new(self, nil )
+               end
+
+               @log.info( "Initializing job...", Log::LV_USER)
+
+               # create source path
+               if not File.exist? @source_path then
+                       FileUtils.mkdir_p @source_path
+               end
+
+               # initialize all sub jobs and add them to "internal_jobs"
+               @sub_jobs.each do |job|
+                       # initialize job
+                       if not job.init or job.status == "ERROR" then
+                               job.status = "ERROR"
+                               @log.info( "Failed to initialize sub-job \"#{job.get_project().name}\" for #{job.os}. (#{job.id})", Log::LV_USER)
+                               job.terminate()
+                       end
+
+                       if job.status != "ERROR" then
+                               job.status = "WAITING"
+                       else
+                               job.status = "ERROR"
+                               @status = "ERROR"
+                       end
+               end
+               if @status == "ERROR" then
+                       return false
+               end
+
+
+               # set up pkgsvr_client
+               first_project = @sub_jobs[0].get_project()
+               @pkgsvr_url = @server.distmgr.get_distribution(first_project.dist_name).pkgsvr_url
+               @pkgsvr_ip = @server.distmgr.get_distribution(first_project.dist_name).pkgsvr_ip
+               @pkgsvr_port = @server.distmgr.get_distribution(first_project.dist_name).pkgsvr_port
+               @pkgsvr_client =  Client.new(@pkgsvr_url, @job_working_dir, @log)
+
+               return true
+       end
+
+
+       #terminate
+       def terminate()
+
+               # report error
+               if @status == "ERROR" then
+                       # register delayed clean action for sub jobs
+                       @sub_jobs.each do |job|
+                               @server.cleaner.clean_afterwards(job.id)
+                       end
+
+                       # register delayed clean action for me
+                       @log.error( "Job is stopped by ERROR" , Log::LV_USER)
+                       @server.cleaner.clean_afterwards(@id)
+
+               elsif @status == "CANCELED" then
+                       # register delayed clean action for sub jobs
+                       @sub_jobs.each do |job|
+                               @server.cleaner.clean_afterwards(job.id)
+                       end
+
+                       # register delayed clean action for me
+                       @log.error( "Job is stopped by CANCEL" , Log::LV_USER)
+                       @server.cleaner.clean_afterwards(@id)
+
+               else
+                       # terminate all sub jobs
+                       @sub_jobs.each do |job|
+                               if not job.log.nil? then job.terminate() end
+                       end
+
+                       # register direct clean action for me
+                       @server.cleaner.clean(@id)
+               end
+
+               # close logger
+               @log.close
+       end
+
+
+       # check building is possible
+       def can_be_built_on?(host_os)
+               return true
+       end
+
+
+       def get_packages()
+               packages = []
+               @sub_jobs.each do |job|
+                       packages = packages + job.get_packages()
+               end
+               packages.uniq!
+
+               return packages
+       end
+
+
+       def get_build_dependencies(target_os)
+               deps = []
+               @sub_jobs.each do |job|
+                       deps = deps + job.get_build_dependencies(target_os)
+               end
+               deps.uniq!
+
+               return deps
+       end
+
+
+       def get_source_dependencies(target_os, host_os)
+               deps = []
+               @sub_jobs.each do |job|
+                       deps = deps + job.get_source_dependencies(target_os,host_os)
+               end
+               deps.uniq!
+
+               return deps
+       end
+
+
+       def is_compatible_with?(o)
+               return false
+       end
+
+       def has_build_dependency?(other_job)
+
+               if has_same_packages?(other_job) or
+                       does_depend_on?(other_job) or
+                       does_depended_by?(other_job) then
+
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       def has_same_packages?( wjob )
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               # same package must have same os
+               if not @os.eql? wjob.os then
+                       return false
+               end
+
+               # check package name
+               get_packages.each do |pkg|
+                       wjob.get_packages().each do |wpkg|
+                               if pkg.package_name == wpkg.package_name then
+                                       #puts "Removed from candiated... A == B"
+                                       return true
+                               end
+                       end
+               end
+
+               return false
+       end
+
+
+       def does_depend_on?( wjob )
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               # compare build dependency
+               get_build_dependencies(@os).each do |dep|
+                       wjob.get_packages().each do |wpkg|
+                               # dep packages of my job must have same name and target os
+                               #  with packages in working job
+                               if dep.package_name == wpkg.package_name and
+                                       dep.target_os_list.include? wjob.os then
+                                       #puts "Removed from candiated... A -> B"
+                                       return true
+                               end
+                       end
+               end
+
+               return false
+       end
+
+
+       def does_depended_by?( wjob )
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               get_packages().each do |pkg|
+                       wjob.get_build_dependencies(wjob.os).each do |dep|
+                               # dep package of working job must have same name and target os
+                               #  with packages in my job
+                               if dep.package_name == pkg.package_name and
+                                       dep.target_os_list.include? @os then
+                                       #puts "Checking... A <- B"
+                                       return true
+                               end
+                       end
+               end
+               return false
+       end
+
+
+       def is_connected?
+               return true
+       end
+
+
+       # return the job is asyncronous job
+       def is_asynchronous_job?
+               return false
+       end
+
+
+       def get_log_url()
+               # only when server support log url
+               if @server.job_log_url.empty? then
+                       return "",""
+               end
+
+               return "#{@server.job_log_url}/#{@id}/log",""
+       end
+
+       #
+       # PROTECTED/PRIVATE METHODS
+       #
+
+
+       # main module
+       protected
+       def job_main()
+               @log.info( "Invoking a thread for MULTI-BUILD Job #{@id}", Log::LV_USER)
+               if @status == "ERROR" then return end
+               @log.info( "New Job #{@id} is started", Log::LV_USER)
+
+               # initialize status map
+               job_status_map = {}
+               @sub_jobs.each do |job|
+                       job_status_map[job.id] = job.status
+               end
+
+               # add to internal job
+               @server.jobmgr.internal_job_schedule.synchronize do
+                       @sub_jobs.each do |job|
+                               # init finished, add internal_jobs
+                               @server.jobmgr.add_internal_job(job)
+                               @log.info( "Added new job \"#{job.get_project().name}\" for #{job.os}! (#{job.id})",
+                                       Log::LV_USER)
+                               if not @server.job_log_url.empty? then
+                                       @log.info( " * Log URL : #{@server.job_log_url}/#{job.id}/log", Log::LV_USER)
+                               end
+                       end
+               end
+
+               # show job status changes
+               all_jobs_finished = false
+               stop_status = "FINISHED"
+               while not all_jobs_finished
+                       all_jobs_finished = true
+                       @sub_jobs.each do |job|
+                               # check status chanaged, if then print
+                               if job_status_map[ job.id ]  != job.status then
+                                       @log.info(" * Sub-Job \"#{job.get_project().name}(#{job.os})\" has entered \"#{job.status}\" state. (#{job.id})", Log::LV_USER)
+                                       job_status_map[ job.id ] = job.status
+                               end
+                               # check all jobs are finished
+                               if job.status != "ERROR" and job.status != "FINISHED" and job.status != "CANCELED" then
+                                       all_jobs_finished = false
+                               end
+                               # check there is some error or cancel
+                               if stop_status == "FINISHED" and
+                                       (job.status == "ERROR" or job.status == "CANCELED") then
+                                       # write url
+                                       write_log_url(job)
+                                       # cancel all other un-finished jobs
+                                       @sub_jobs.each do |sub|
+                                               if sub.status != "ERROR" and sub.status != "FINISHED" and
+                                                       sub.status != "CANCELED" and sub.cancel_state == "NONE" then
+                                                       @log.info(" * Sub-Job \"#{sub.get_project().name}(#{sub.os})\" has entered \"CANCELING\" state. (#{sub.id})", Log::LV_USER)
+                                                       sub.cancel_state = "INIT"
+                                               end
+                                       end
+
+                                       stop_status = job.status
+                                       break
+                               end
+                       end
+
+                       #
+                       sleep 1
+               end
+
+               if stop_status == "ERROR" or stop_status == "CANCELED" then
+                       @status = stop_status
+                       return
+               end
+
+               # upload
+               if not upload() then
+                       @status = "ERROR"
+                       return
+               end
+
+               # INFO. don't change this string
+               @log.info( "Job is completed!", Log::LV_USER)
+               @status = "FINISHED"
+       end
+
+
+       private
+       def upload()
+               @log.info( "Uploading ...", Log::LV_USER)
+
+               # get package path list
+               binpkg_path_list = Dir.glob("#{@source_path}/*_*_*.zip")
+
+               # upload
+               u_client = Client.new( @pkgsvr_url, nil, @log )
+               snapshot = u_client.upload( @pkgsvr_ip, @pkgsvr_port, binpkg_path_list, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd)
+
+               if snapshot.nil? then
+                       @log.info( "Upload failed...", Log::LV_USER)
+
+                       return false
+               end
+
+               # update local
+               @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER)
+               @pkgsvr_client.update
+               @log.info("Snapshot: #{snapshot}", Log::LV_USER)
+
+               return true
+       end
+
+
+       # write web url for log
+       private
+       def write_log_url(job)
+               url,remote_url = job.get_log_url()
+               if not url.empty? then
+                       @log.info( " ** Log1: #{url}", Log::LV_USER)
+               end
+               if not remote_url.empty? then
+                       @log.info( " ** Log2: #{remote_url}", Log::LV_USER)
+               end
+       end
+
+end
diff --git a/src/build_server/PackageSync.rb b/src/build_server/PackageSync.rb
new file mode 100644 (file)
index 0000000..afc2598
--- /dev/null
@@ -0,0 +1,238 @@
+=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 "Action.rb"
+require "ScheduledActionHandler.rb"
+
+
+class PackageSyncAction < Action
+       attr_accessor :pkgsvr_url, :dist_name
+       @@new_id = 0
+
+       def initialize( time, url, dist_name, server )
+               super(time, server.pkg_sync_period)
+               my_id = @@new_id
+               @@new_id += 1
+               @pkgsvr_url = url
+               @dist_name = dist_name
+               @server = server
+               @pkgsvr_client = nil
+               @main_client = nil
+               @sync_root = "#{@server.path}/sync/#{my_id}"
+               @download_path = "#{@sync_root}/remote"
+               @original_path = "#{@sync_root}/main"
+       end
+
+
+       def init
+               # create directory
+               if File.exist? @download_path then
+                       FileUtils.rm_rf @download_path
+                       FileUtils.rm_rf @original_path
+               end
+
+               FileUtils.mkdir_p @download_path
+               FileUtils.mkdir_p @original_path
+
+               # create client
+               @pkgsvr_client = Client.new( @pkgsvr_url, @download_path, @server.log )
+
+               main_url = @server.distmgr.get_distribution(@dist_name).pkgsvr_url
+               @main_client = Client.new( main_url, @original_path, @server.log )
+       end
+
+
+       def execute
+               @server.log.info "Executing package-sync action for server \"#{@pkgsvr_url}\""
+
+               begin
+                       execute_internal()
+               rescue => e
+                       @server.log.error e.message
+                       @server.log.error e.backtrace.inspect
+               end
+       end
+
+
+       private
+       def execute_internal()
+               # check update
+               pkgs = check_package_update
+
+               # request to register
+               registered_jobs = []
+
+               # if updates are found, download them
+               downloaded_files = []
+               pkgs.each do  |pkg|
+                       pkg_name=pkg[0]; os=pkg[1]; prj=pkg[2]
+
+                       file_paths = @pkgsvr_client.download(pkg_name, os, false)
+                       if file_paths.nil? then next end
+                       downloaded_files += file_paths
+
+                       file_paths.each do |file_path|
+                               @server.log.info "Creating new job for registering \"#{file_path}\""
+                               new_job = @server.jobmgr.create_new_register_job( file_path, @dist_name )
+                               if new_job.nil? then
+                                       @server.log.error "Creating job failed: #{prj.name} #{pkg_name} #{@dist_name}"
+                                       next
+                               end
+                               new_job.priority = CommonJob::AUTO_JOB_PRIORITY
+                               new_job.create_logger( nil )
+
+                               # add
+                               @server.jobmgr.add_job( new_job )
+                               registered_jobs.push new_job
+                       end
+               end
+
+               # wait for finish all jobs
+               all_jobs_finished = false
+               while not all_jobs_finished
+                       unfinished_jobs = registered_jobs.select do  |j|
+                               (j.status != "ERROR" and j.status != "FINISHED" and j.status != "CANCELED")
+                       end
+                       if unfinished_jobs.empty? then
+                               all_jobs_finished = true
+                       else
+                               sleep 10
+                       end
+               end
+
+               # remove files
+               downloaded_files.each do  |file_path|
+                       @server.log.info "Removed downloaded file: \"#{file_path}\""
+                       FileUtils.rm_rf file_path
+               end
+       end
+
+
+       protected
+       def check_package_update
+               pkgs = []
+
+               # update
+               @pkgsvr_client.update()
+               @main_client.update()
+
+               # for all BINARY project
+               bin_prjs = @server.prjmgr.get_all_projects().select { |p| 
+                       (p.type == "BINARY" and p.dist_name == @dist_name) 
+               }
+               bin_prjs.each do  |p|
+                       pkg_name = p.pkg_name
+                       p.os_list.each do  |os|
+                               # get pkg version in server
+                               main_ver = @main_client.get_attr_from_pkg(pkg_name, os, "version")
+                               remote_ver = @pkgsvr_client.get_attr_from_pkg(pkg_name, os, "version")
+                               if remote_ver.nil? then next end
+
+                               if main_ver.nil? or Version.new(main_ver) < Version.new(remote_ver) then
+                                       pkgs.push [pkg_name, os, p]
+                               end
+                       end
+               end
+
+               return pkgs
+       end
+
+end
+
+
+class PackageServerSynchronizer
+       attr_accessor :quit
+
+       # init
+       def initialize( server )
+               @server = server
+               @handler = ScheduledActionHandler.new
+       end
+
+
+       # start thread
+       def start()
+
+               # start thread for handling action
+               @handler.start
+
+               Thread.new do
+                       monitor()
+               end
+       end
+
+
+       private
+       def monitor()
+               while(true)
+                       # wait 10 seconds
+                       sleep 10
+
+                       # get info from DB
+                       syncs = @server.get_sync_package_servers()
+
+                       # check removal
+                       @handler.get_actions().each do |act|
+                               exist = false
+                               syncs.each do |sync|
+                                       url=sync[0]; dist_name=sync[1]
+                                       if url == act.pkgsvr_url and dist_name == act.dist_name then 
+                                               exist = true 
+                                               break
+                                       end
+                               end
+                               if not exist then
+                                       @handler.unregister(act)
+                                       @server.log.info "Unregistered package-sync action!: #{act.dist_name} <= \"#{act.pkgsvr_url}\""
+                               end
+                       end
+                       
+                       # check add/modify
+                       syncs.each do  |sync|
+                               url=sync[0]; dist_name=sync[1]
+                               exist = false
+                               @handler.get_actions().each do |act|
+                                       if act.pkgsvr_url == url and act.dist_name == dist_name then
+                                               exist = true
+                                       end     
+                               end
+                               
+                               if not exist then
+                                       new_time = Time.new + 10
+                                       @handler.register( PackageSyncAction.new(new_time, url, dist_name, @server) )
+                                       @server.log.info "Registered package-sync action!: #{dist_name} <= \"#{url}\""
+                               end
+                       end
+
+               end
+       end
+end
diff --git a/src/build_server/ProjectManager.rb b/src/build_server/ProjectManager.rb
new file mode 100644 (file)
index 0000000..c717213
--- /dev/null
@@ -0,0 +1,364 @@
+=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'
+require 'dbi'
+$LOAD_PATH.unshift File.dirname(__FILE__)
+require "GitBuildProject.rb"
+require "BinaryUploadProject.rb"
+require "MultiBuildJob.rb"
+require "PackageManifest.rb"
+require "package.rb"
+
+class ProjectManager
+
+       # initialize
+       def initialize( server )
+               @server = server
+               @project_root = "#{@server.path}/projects"
+       end
+
+
+       # load existing project from server configuration
+       def load()
+               # check project root
+               if not File.exist? @project_root then
+                       FileUtils.mkdir_p @project_root
+               end
+       end
+
+
+       # get_project of the name
+       def get_project(name, dist_name)
+               @server.get_db_connection() do |db|
+                       return get_project_internal(name, dist_name, db)
+               end
+
+               return nil
+       end
+
+
+       def get_all_projects_summary()
+               @server.get_db_connection() do |db|
+                       return CommonProject.get_all_project_rows(db)
+               end
+       end
+
+       def get_all_projects()
+               result = []
+
+               @server.get_db_connection() do |db|
+                       rows = CommonProject.get_all_project_rows(db)
+                       rows.each do |row|
+                               if row[:ptype] == "GIT" then
+                                       prj = GitBuildProject.load(row[:name], row[:dist_name], @server, db)
+                               else
+                                       prj = BinaryUploadProject.load(row[:name], row[:dist_name], @server, db)
+                               end
+                               if not prj.nil? then result.push prj end
+                       end
+                       return result
+               end
+
+               return result
+       end
+
+
+       def add_git_project(name, repos, branch, passwd, os_list, dist_name)
+               new_prj = nil
+               result = @server.get_db_connection() do |db|
+                       prj = get_project_internal(name, dist_name, db)
+                       if not prj.nil? then
+                               @server.log.error "Adding project failed!: the project \"#{name}\"(#{dist_name}) already exists"
+                               return false
+                       end
+                               
+                       # create new object
+                       new_prj = GitBuildProject.new(name, @server, os_list, dist_name, repos, branch)
+                       if not passwd.nil? and not passwd.empty? then
+                               new_prj.passwd = passwd
+                       end
+
+                       # save to db
+                       new_prj.save(db)
+               end
+
+               if result then 
+                       # authorize admin to access
+                       @server.qualify_admin_to_access(new_prj.get_project_id())
+                       @server.log.info "Added new GIT project \"#{name}\"(#{dist_name})"
+               end
+
+               return result
+       end
+
+
+       def add_binary_project(name, pkg_name, passwd, os_list, dist_name)
+               new_prj = nil
+               result = @server.get_db_connection() do |db|
+                       prj = get_project_internal(name, dist_name, db)
+                       if not prj.nil? then
+                               @server.log.error "Adding project failed!: the project \"#{name}\"(#{dist_name}) already exists"
+                               return false
+                       end
+                       
+                       # create new object
+                       new_prj = BinaryUploadProject.new(name, @server, os_list, dist_name, pkg_name)
+                       if not passwd.nil? and not passwd.empty? then
+                               new_prj.passwd = passwd
+                       end
+
+                       # save to db
+                       new_prj.save(db)
+
+                       # init
+                       new_prj.init()
+               end
+
+               if result then
+                       # authorize admin to access
+                       @server.qualify_admin_to_access(new_prj.get_project_id())
+                       @server.log.info "Added new BINARY project \"#{name}\"(#{dist_name})"
+               end
+
+               return result
+       end
+
+
+       def remove_project( name, dist_name )
+
+               result = @server.get_db_connection() do |db|
+                       prj = get_project_internal(name, dist_name, db)
+                       if prj.nil? then
+                               @server.log.error "The project \"#{name}\"(#{dist_name}) does not exists on server"
+                               @server.log.error "Removing project failed!"
+                               return false
+                       end
+                       # unload from DB
+                       prj.unload(db)
+
+                       # remove project directory
+                       FileUtils.rm_rf prj.path
+               end
+
+               if result then
+                       @server.log.info "Removed the project \"#{name}\"(#{dist_name})"
+               end
+               return result
+       end
+
+       public
+       def get_project_accessable(project_name, dist_name, user_id)
+               prj = get_project(project_name, dist_name)
+               result = nil
+               @server.get_db_connection() do |db|
+                       result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses 
+                                                       WHERE user_groups.user_id = #{user_id} and 
+                                                       user_groups.group_id = group_project_accesses.group_id and
+                                                       group_project_accesses.project_id = #{prj.get_project_id} and
+                                                       group_project_accesses.build = 'TRUE'"
+               end
+               return (not result.nil?)
+       end
+
+       def get_project_pkg_name_accessable(pkg_name, dist_name, user_id)
+               result = nil
+               prj = get_project_from_package_name(pkg_name, dist_name)
+               @server.get_db_connection() do |db|
+                       result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses 
+                                                       WHERE user_groups.user_id = #{user_id} and 
+                                                       user_groups.group_id = group_project_accesses.group_id and
+                                                       group_project_accesses.project_id = #{prj.get_project_id} and
+                                                       group_project_accesses.build = 'TRUE'"
+               end
+               return (not result.nil?)
+       end
+
+       # create new job for project
+       # if cannot create, return nil
+       def create_new_job( name, os, dist_name )
+               prj = get_project( name, dist_name )
+               if prj.nil? then
+                       @server.log.error "Cannot get project info \"#{name}\"(#{dist_name})"
+               end
+
+               return prj.create_new_job( os )
+       end
+
+
+       # create new multi build job
+       def create_new_multi_build_job( sub_job_list )
+               result = MultiBuildJob.new( @server )
+
+               sub_job_list.each do |job|
+                       result.add_sub_job( job )
+               end
+
+               return result
+       end
+
+
+       # create new full job
+       def create_new_full_build_job(dist_name="BASE")
+               # create multi job
+               result = MultiBuildJob.new( @server )
+
+               # create sub jobs
+               get_all_projects().each do |prj|
+                       if prj.type != "GIT" then next end
+                       if prj.dist_name != dist_name then next end
+
+                       prj.os_list.each do |os|
+                               if not @server.supported_os_list.include? os then next end
+
+                               new_job = create_new_job( prj.name, os, dist_name )
+                               if new_job.nil? then next end
+
+                               # This make project to build
+                               # even though there is a package of same version on pkg-server
+                               new_job.set_force_rebuild(true)
+
+                               # add to multi job
+                               result.add_sub_job( new_job )
+                       end
+               end
+
+               return result
+       end
+
+
+       # get project that includes specified pkg name and os
+       # will return [project,os,ver] list
+       def get_projects_from_pkgs(pkgs, dist_name="BASE")
+               result = []
+               get_all_projects().each do |prj|
+                       # check distribution name
+                       if prj.dist_name != dist_name then next end
+
+                       pkgs.each do |pkg|
+                               name = pkg.package_name
+                               ver =  pkg.version
+                               os = pkg.os
+
+                               # check project provide target package
+                               if prj.include_package?(name, ver, os) then
+                                       result.push [prj, os, ver]
+                                       break
+                               end
+                       end
+               end
+
+               return result
+       end
+
+
+       def get_project_from_package_name(pkg_name, dist_name)
+               @server.get_db_connection() do |db|
+                       return get_project_from_pkg_name_internal(pkg_name,dist_name,db)
+               end
+               return nil
+       end
+
+
+       # get project from git repository
+       def get_git_project( repos, dist_name )
+               get_all_projects().each do |prj|
+                       # check project's distribution
+                       if prj.dist_name != dist_name then next end
+                       if prj.type == "GIT" and prj.repository == repos then
+                               return prj
+                       end
+               end
+
+               return nil
+       end
+
+
+       def create_unnamed_git_project(repos, dist_name)
+               name = "UNNAMED_PRJ_#{get_all_projects().count}"
+               branch = "master"
+               passwd = nil
+               os_list = Utils.get_all_OSs()
+               os_list.each do |os|
+                       @server.add_supported_os(os)
+               end
+               # add
+               add_git_project(name , repos, branch, passwd, os_list, dist_name)
+               # get
+               return get_project(name, dist_name)
+       end
+
+
+       # write configuration
+       def write_configuration(name, repos, branch, passwd, os_list  )
+               config_file = "#{@project_root}/#{name}/build"
+               File.open( config_file, "w" ) do |f|
+                       f.puts "TYPE=GIT"
+                       if not passwd.nil? and not passwd.empty? then
+                               f.puts "PASSWD=#{passwd}"
+                       end
+                       f.puts "GIT_REPOSITORY=#{repos}"
+                       f.puts "GIT_BRANCH=#{branch}"
+                       f.puts "OS_LIST=#{os_list.join(",")}"
+               end
+       end
+
+
+       # write configuration
+       def write_configuration_for_binary_project(name, pkg_name, passwd, os_list  )
+               config_file = "#{@project_root}/#{name}/build"
+               File.open( config_file, "w" ) do |f|
+                       f.puts "TYPE=BINARY"
+                       if not passwd.nil? and not passwd.empty? then
+                               f.puts "PASSWD=#{passwd}"
+                       end
+                       f.puts "PACKAGE_NAME=#{pkg_name}"
+                       f.puts "OS_LIST=#{os_list.join(",")}"
+               end
+       end
+
+
+       private
+       def get_project_internal(name, dist_name, db)
+               row = CommonProject.get_project_row(name, dist_name, db)
+               if row.nil? then return nil end
+               prj_type = row['ptype']
+
+               if prj_type == "GIT" then
+                       return GitBuildProject.load(name, dist_name, @server, db)
+               else
+                       return BinaryUploadProject.load(name, dist_name, @server, db)
+               end
+       end
+
+       private
+       def get_project_from_pkg_name_internal(pkg_name, dist_name, db)
+               row = CommonProject.get_project_from_pkg_name_row(pkg_name, dist_name, db)
+               return ( row.nil? ) ? nil : BinaryUploadProject.load(row[:name], dist_name, @server, db)
+       end
+end
diff --git a/src/build_server/RegisterPackageJob.rb b/src/build_server/RegisterPackageJob.rb
new file mode 100644 (file)
index 0000000..b745a3c
--- /dev/null
@@ -0,0 +1,549 @@
+=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__))+"/plkg_server"
+require "client.rb"
+require "PackageManifest.rb"
+require "Version.rb"
+require "JobLog.rb"
+require "mail.rb"
+require "utils.rb"
+require "ReverseBuildChecker.rb"
+require "CommonJob.rb"
+
+class RegisterPackageJob < CommonJob
+
+       attr_accessor :source_path
+       attr_accessor :pkgsvr_client, :thread, :pkg_type
+       attr_accessor :pkg_name, :pkginfo, :cancel_state
+       attr_accessor :no_reverse
+
+
+       # initialize
+       def initialize( local_path, project, server, ftpurl=nil, dist_name=nil )
+               super(server)
+               @log = nil
+               @type = "REGISTER"
+               @no_reverse = false
+
+               @host_os = Utils::HOST_OS
+               if not project.nil? then
+                       @pkgsvr_url = @server.distmgr.get_distribution(project.dist_name).pkgsvr_url
+                       @pkgsvr_ip = @server.distmgr.get_distribution(project.dist_name).pkgsvr_ip
+                       @pkgsvr_port = @server.distmgr.get_distribution(project.dist_name).pkgsvr_port
+               else
+                       @pkgsvr_url = @server.distmgr.get_distribution(dist_name).pkgsvr_url
+                       @pkgsvr_ip = @server.distmgr.get_distribution(dist_name).pkgsvr_ip
+                       @pkgsvr_port = @server.distmgr.get_distribution(dist_name).pkgsvr_port
+               end
+               @job_root = "#{@server.path}/jobs/#{@id}"
+               @source_path = @job_root+"/temp"
+               @job_working_dir=@job_root+"/works"
+               @buildroot_dir = "#{@job_root}/buildroot"
+               @cancel_state = "NONE"
+
+               @local_path=local_path
+               @file_path = nil
+               @filename = File.basename(local_path)
+               if @filename =~ /.*_.*_.*\.zip/ then
+                       @pkg_type = "BINARY"
+                       new_name = @filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+                       @pkg_name = new_name.split(",")[0]
+                       @pkg_version = new_name.split(",")[1]
+                       @os = new_name.split(",")[2]
+               else
+                       @pkg_type = "ARCHIVE"
+                       @pkg_name = @filename
+               end
+               @pkginfo = nil #This info is valid only for BINARY package
+               @project = project
+               if not dist_name.nil? then
+                       @dist_name = dist_name 
+               elsif not @project.nil? then
+                       @dist_name = @project.dist_name
+               else
+                       @dist_name = "BASE"     
+               end
+               @auto_remove = false
+       end
+
+
+       def get_distribution_name()
+               return @dist_name
+       end
+
+
+       def get_buildroot()
+               return @buildroot_dir
+       end
+
+
+       def is_rev_build_check_job()
+               return false
+       end
+
+
+       def set_auto_remove(value)
+               @auto_remove=value
+       end
+
+
+       def set_no_reverse()
+               @no_reverse = true
+       end
+
+
+       #
+       def init
+               # mkdir
+               if not File.exist? @job_root then
+                       FileUtils.mkdir_p @job_root
+               end
+
+               if @cancel_state != "NONE" then return false end
+
+               # create logger
+               if @log.nil? then
+                       @log = JobLog.new(self, nil )
+               end
+
+               if @cancel_state != "NONE" then return false end
+
+               @log.info( "Initializing job...", Log::LV_USER)
+
+               # create dummy source path
+               if not File.exist? @source_path then
+                       FileUtils.mkdir_p @source_path
+               end
+
+               # copy package file to source path
+               @file_path = "#{@source_path}/#{File.basename(@local_path)}"
+               if not File.exist? @local_path then
+                       @log.error( "File not found!", Log::LV_USER)
+                       @status = "ERROR"
+                       return false
+               else
+                       if @auto_remove then
+                               # if remote upload remove file and its directory
+                               FileUtils.mv(@local_path, @file_path)
+                               FileUtils.rm_rf("#{File.dirname(@local_path)}")
+                       else
+                               FileUtils.cp(@local_path, @file_path)
+                       end
+               end
+
+               if @cancel_state != "NONE" then return false end
+
+               # set up pkgsvr_client
+               @pkgsvr_client =  Client.new(@pkgsvr_url, @job_working_dir, @log)
+
+               if @cancel_state != "NONE" then return false end
+
+               # check if the os is supported by build server
+               if @pkg_type == "BINARY" and
+                       not @server.supported_os_list.include? @os then
+                       @log.error( "Unsupported OS \"#{@os}\" is used!", Log::LV_USER)
+                       @status = "ERROR"
+                       return false
+               end
+
+               if @cancel_state != "NONE" then return false end
+
+               # checking version if not reverse-build job
+               if @pkg_type == "BINARY" then
+                       # extrac pkg file
+                       cmd = "cd \"#{@source_path}\";unzip #{@file_path}"
+                       if not Utils.execute_shell(cmd) then
+                               @log.error( "Extracting package file failed!", Log::LV_USER)
+                               @status = "ERROR"
+                               return false
+                       end
+
+                       if @cancel_state != "NONE" then return false end
+
+                       # set up pkg info
+                       begin
+                               @pkginfo = PackageManifest.new("#{@source_path}/pkginfo.manifest")
+                       rescue => e
+                               @log.error( e.message, Log::LV_USER)
+                               @status = "ERROR"
+                               return false
+                       end
+
+                       #if @server.changelog_check and not @pkginfo.packages[0].does_change_exist? then
+                       #       @log.error( "change log not found", Log::LV_USER )
+                       #       return false
+                       #end
+
+                       if @cancel_state != "NONE" then return false end
+
+                       if not check_package_version() then
+                               @status = "ERROR"
+                               return false
+                       end
+               end
+
+               if @cancel_state != "NONE" then return false end
+
+               return true
+       end
+
+
+       #terminate
+       def terminate()
+               # report error
+               if @status == "ERROR" then
+                       @log.error( "Job is stopped by ERROR" , Log::LV_USER)
+                       @server.cleaner.clean_afterwards(@id)
+               else
+                       @log.info( "Job is FINISHED successfully!" , Log::LV_USER)
+
+                       # if succeeded, register source info and copy pkginfo.manifest
+                       if not @project.nil? then
+                               @log.info( "Updating the source info for project \"#{@project.name}\"" , Log::LV_USER)
+                               @project.save_source_info( @pkginfo.get_version(), '')
+                               @project.save_package_info_from_manifest( @pkginfo.get_version(),"#{@source_path}/pkginfo.manifest", @os)
+                       end
+
+                       # clean up
+                       @server.cleaner.clean(@id)
+               end
+
+               # close logger
+               @log.close
+       end
+
+
+       #cancel
+       def cancel()
+               if not @log.nil? then
+                       @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER)
+               end
+       end
+
+
+       # check building is possible
+       def can_be_built_on?(host_os)
+               return true
+       end
+
+
+       def get_packages()
+               if @pkg_type == "BINARY" then
+                       return @pkginfo.packages
+               else
+                       return []
+               end
+       end
+
+
+       def get_build_dependencies(target_os)
+               return []
+       end
+
+
+       def get_source_dependencies(target_os,host_os)
+               return  []
+       end
+
+
+       def is_compatible_with?(o)
+               return false
+       end
+
+
+       def has_build_dependency?(other_job)
+               if has_same_packages?(other_job) or
+                       does_depended_by?(other_job) then
+
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       def has_same_packages?( wjob )
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               if @type != wjob.type then return false end
+
+               case @pkg_type
+               when "BINARY"
+                       if @pkg_name == wjob.pkg_name and
+                               @os == wjob.os then
+                               return true
+                       end
+               when "ARCHIVE"
+                       if @pkg_name == wjob.pkg_name then return true end
+               end
+
+               return false
+       end
+
+
+       # binary/archive package should not have build-dependencies
+       def does_depend_on?( wjob )
+               return false
+       end
+
+
+       def does_depended_by?( wjob )
+               # must have same distribution
+               if get_distribution_name() != wjob.get_distribution_name() then
+                       return false
+               end
+
+               if @pkg_type == "BINARY" then
+                       wjob.get_build_dependencies(wjob.os).each do |dep|
+                               # dep package of working job must have same name and target os
+                               #  with packages in my job
+                               if dep.package_name == @pkg_name and
+                                       dep.target_os_list.include? @os then
+                                       #puts "Checking... A <- B"
+                                       return true
+                               end
+                       end
+               else
+                       wjob.get_source_dependencies(wjob.os,@host_os).each do |dep|
+                               if dep.package_name == @pkg_name then
+                                       return true
+                               end
+                       end
+               end
+
+               return false
+       end
+
+
+       def is_connected?
+               return true
+       end
+
+
+       # return the job is asyncronous job
+       def is_asynchronous_job?
+               return false
+       end
+
+
+       def progress
+               return ""
+       end
+
+
+       def get_log_url()
+               # only when server support log url
+               if @server.job_log_url.empty? then
+                       return "",""
+               end
+
+               return "#{@server.job_log_url}/#{@id}/log",""
+       end
+
+       #
+       # PROTECTED METHODS
+       #
+
+
+       # main module
+       protected
+       def job_main()
+               @log.info( "Invoking a thread for REGISTER Job #{@id}", Log::LV_USER)
+               if @status == "ERROR" then return  end
+               @log.info( "New Job #{@id} is started", Log::LV_USER)
+
+               # clean build
+               if not ReverseBuildChecker.check( self, true ).empty? then
+                       @status = "ERROR"
+                       @log.error( "Reverse-build-check failed!" )
+                       return
+               end
+
+               # if this package has compatible OS, check
+               if @pkg_type == "BINARY" and
+                       @pkginfo.packages[0].os_list.count > 1 then
+
+                       pkg = @pkginfo.packages[0]
+                       pkg.os_list.each do |os|
+                               if @os == os then next end
+
+                               # skip when the os does not exist in project's supported os list
+                               if not @project.nil? and not @project.os_list.include? os then next end
+
+                               # skip when there is higher version of the package
+                               ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version")
+                               if not ver_svr.nil? and
+                                       Version.new(@pkg_version) <= Version.new(ver_svr) then next end
+
+                               # make new package file for compatible OS
+                               newfile = "#{@pkg_name}_#{@pkg_version}_#{os}.zip"
+                               @log.info( "Copying #{@filename} to #{newfile}" )
+                               FileUtils.cp(@file_path,"#{@source_path}/#{newfile}")
+
+                               # reverse check
+                               if not @no_reverse then
+                                       if not ReverseBuildChecker.check( self, true, os ) then
+                                               @status = "ERROR"
+                                               @log.error( "Reverse-build-check failed!" )
+                                               return
+                                       end
+                               end
+                       end
+               end
+
+               # upload
+               if not upload() then
+                       @status = "ERROR"
+                       return
+               end
+
+               # INFO. don't change this string
+               @log.info( "Job is completed!", Log::LV_USER)
+               @status = "FINISHED"
+       end
+
+
+       # build projects that dependes on me
+       # can ignore some projects
+       def check_reverse_build( target_os )
+               @log.info( "Checking reverse build dependency ...", Log::LV_USER)
+
+               # get reverse-dependent projects
+               rev_pkgs = []
+               if @pkg_type == "BINARY" then
+                       rev_pkgs += @pkgsvr_client.get_reverse_build_dependent_packages(@pkg_name, target_os)
+               else
+                       rev_pkgs += @pkgsvr_client.get_reverse_source_dependent_packages(@pkg_name)
+               end
+
+               rev_projects = @server.prjmgr.get_projects_from_pkgs(rev_pkgs, get_distribution_name())
+
+               # create reverse build job
+               rev_build_jobs = []
+               rev_projects.each do |p|
+                       prj = p[0]
+                       os = p[1]
+                       version = p[2]
+
+                       if prj.type != "GIT" then next end
+
+                       # create sub jobs for checking
+                       new_job = prj.create_new_job_from_version(os, version)
+                       new_job.set_rev_build_check_job(self)
+
+                       rev_build_jobs.push new_job
+               end
+
+               # reverse build
+               if rev_build_jobs.count > 0 then
+                       rev_prjs_txt = rev_build_jobs.map {|j| "#{j.get_project().name}(#{j.os})"}.join(", ")
+                       @log.info( " * Will check reverse-build for next projects: #{rev_prjs_txt}", Log::LV_USER)
+               end
+               rev_build_jobs.each do |new_job|
+                       @log.info( " * Checking reverse-build ... #{new_job.get_project().name}(#{new_job.id})", Log::LV_USER)
+                       # job init
+                       result = new_job.init()
+                       # if init is succeeded!, try to execute
+                       if result then
+                               # check available server
+                               rserver = @server.get_available_server( new_job )
+                               if rserver != nil and rserver != @server then
+                                       new_job.set_remote_job( rserver )
+                               end
+                               # execute
+                               new_job.execute(true)
+                               if new_job.status == "ERROR" then result = false end
+                       end
+
+                       # check result
+                       if not result then
+                               return false
+                       end
+               end
+
+               return true
+       end
+
+
+       def upload()
+               @log.info( "Uploading ...", Log::LV_USER)
+
+               # get package path list
+               if @pkg_type == "ARCHIVE" then
+                       binpkg_path_list = Dir.glob("#{@source_path}/#{@pkg_name}")
+               else
+                       binpkg_path_list = Dir.glob("#{@source_path}/*_*_*.zip")
+               end
+
+               # upload
+               u_client = Client.new( @pkgsvr_url, nil, @log )
+               snapshot = u_client.upload( @pkgsvr_ip, @pkgsvr_port, binpkg_path_list, @server.ftp_addr, @server.ftp_port, @server.ftp_username, @server.ftp_passwd)
+
+               if snapshot.nil? then
+                       @log.info( "Upload failed...", Log::LV_USER)
+
+                       return false
+               end
+
+               # update local
+               @log.info( "Upload succeeded. Sync local pkg-server again...", Log::LV_USER)
+               @pkgsvr_client.update
+               @log.info("Snapshot: #{snapshot}", Log::LV_USER)
+
+               return true
+       end
+
+
+       # check if local package version is greater than server
+       def     check_package_version()
+               @log.info( "Checking package version ...", Log::LV_USER)
+
+               # package update
+               @pkgsvr_client.update
+
+               @pkginfo.packages.each do |pkg|
+                       ver_local = pkg.version
+                       #ver_svr = @pkgsvr_client.get_package_version( pkg.package_name, @os )
+                       ver_svr = @pkgsvr_client.get_attr_from_pkg( pkg.package_name, @os, "version")
+                       if not ver_svr.nil? and Version.new(ver_local) <= Version.new(ver_svr) then
+                               @log.error( "Version must be increased : #{ver_local} <= #{ver_svr}", Log::LV_USER)
+                               return false
+                       end
+               end
+
+               return true
+       end
+end
index 8e9355b8b84634bacfae6ab6f7b0dff4f3e536f2..4645786a13f60aa48b38b18d617440edaa2a5f9c 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  RemoteBuildJob.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -31,14 +31,15 @@ $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "BuildJob.rb"
 require "utils.rb"
 
+
 class RemoteBuildJob < BuildJob
        attr_accessor :id
 
        # initialize
-       def initialize (id)
-               super()
+       def initialize (id,server)
+               super(nil,nil,server)
+               # overide id
                @id = id
                @type = nil
-               @outstream = nil
        end
 end
diff --git a/src/build_server/RemoteBuildServer.rb b/src/build_server/RemoteBuildServer.rb
new file mode 100644 (file)
index 0000000..b038be1
--- /dev/null
@@ -0,0 +1,248 @@
+=begin
+
+ RemoteBuildServer.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 "RemoteBuildJob.rb"
+require "BuildComm.rb"
+require 'thread'
+
+class RemoteBuildServer
+       attr_accessor :id, :ip, :port, :description, :status, :host_os
+       attr_accessor :max_working_jobs, :working_jobs, :waiting_jobs, :working_job_count, :waiting_job_count
+       attr_accessor :path
+       attr_accessor :jobmgr, :distmgr
+
+       # initialize
+       def initialize(ip, port, desc)
+               @id = -1
+               @ip = ip
+               @port = port
+               @description = desc
+               @status = "DISCONNECTED"
+               @host_os = Utils::HOST_OS
+               @max_working_jobs = 2
+               @working_jobs = []
+               @working_job_count = 0
+               @waiting_jobs = []
+               @waiting_job_count = 0
+               @path = ""
+               @file_transfer_cnt_mutex = Mutex.new
+               @file_transfer_cnt = 0
+               @jobmgr = nil
+               @distmgr = nil
+       end
+
+
+       # check the job can be built on this server
+       def can_build?(job)
+
+               # check me
+               if job.can_be_built_on? @host_os then
+                       return true
+               end
+
+               return false
+       end
+
+
+       # query remote server info & update server state
+       def update_state(db)
+
+               # send
+               #@status = "DISCONNECTED"
+               client = BuildCommClient.create( @ip, @port )
+               if client.nil? then
+                       @status = "DISCONNECTED"
+                       db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}"
+                       return
+               end
+               if client.send("QUERY|SYSTEM") then
+                       result = client.read_lines do |l|
+                               tok = l.split(",").map { |x| x.strip }
+                               @host_os = tok[0]
+                               @max_working_jobs = tok[1].to_i
+                               @status = "RUNNING"
+                       end
+                       if not result then @status = "DISCONNECTED" end
+               else
+                       @status = "DISCONNECTED"
+               end
+               client.terminate
+               if @status == "DISCONNECTED" then
+                       db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}"
+                       return
+               end
+
+               # send
+               @working_jobs = []
+               @waiting_jobs = []
+               client = BuildCommClient.create( @ip, @port )
+               if client.nil? then
+                       @status = "DISCONNECTED"
+                       db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}"
+                       return
+               end
+               if client.send("QUERY|JOB") then
+                       result = client.read_lines do |l|
+                               tok = l.split(",").map { |x| x.strip }
+
+                               job_status = tok[0]
+                               job_id = tok[1]
+                               new_job = RemoteBuildJob.new(job_id,self)
+                               case job_status
+                               when "WAITING", "JUST_CREATED", "INITIALIZING"
+                                       @waiting_jobs.push new_job
+                               when "WORKING"
+                                       @working_jobs.push new_job
+                               else
+                                       #puts "Uncontrolled status"
+                               end
+                       end
+                       if not result then @status = "DISCONNECTED" end
+               else
+                       @status = "DISCONNECTED"
+               end
+               client.terminate
+               if @status == "DISCONNECTED" then
+                       db.do "UPDATE remote_build_servers SET status = 'DISCONNECTED', max_job_count = 0, working_job_count = 0, waiting_job_count = 0 WHERE id = #{@id}"
+               else
+                       @working_job_count = @working_jobs.count
+                       @waiting_job_count = @waiting_jobs.count
+                       db.do "UPDATE remote_build_servers SET
+                               status = '#{@status}',
+                               supported_os_id = (SELECT supported_os.id FROM supported_os WHERE supported_os.name = '#{@host_os}'),
+                               max_job_count = #{@max_working_jobs},
+                               working_job_count = #{@working_job_count},
+                               waiting_job_count = #{@waiting_job_count} WHERE id = #{@id}"
+               end
+       end
+
+
+       # return available working slot
+       def get_number_of_empty_room
+               return @max_working_jobs - @working_job_count
+       end
+
+
+       # check there are working jobs
+       def has_working_jobs
+               return (@working_job_count > 0)
+       end
+
+
+       # check there are waiting jobs
+       def has_waiting_jobs
+               return (@waiting_job_count > 0)
+       end
+
+
+       def add_file_transfer()
+               @file_transfer_cnt_mutex.synchronize do
+                       @file_transfer_cnt += 1
+               end
+       end
+
+       def remove_file_transfer()
+               @file_transfer_cnt_mutex.synchronize do
+                       @file_transfer_cnt -= 1
+               end
+       end
+
+       def get_file_transfer_cnt()
+               return @file_transfer_cnt
+       end
+
+
+       def set_id(id)
+               @id = id
+       end
+
+
+       def self.create_table(db, inc, post_fix)
+               db.do "CREATE TABLE remote_build_servers ( 
+                       id INTEGER PRIMARY KEY #{inc}, 
+                       svr_addr VARCHAR(64) NOT NULL UNIQUE, 
+                       description VARCHAR(256),
+                       status VARCHAR(32),
+                       supported_os_id INTEGER,
+                       max_job_count INTEGER,
+                       working_job_count INTEGER,
+                       waiting_job_count INTEGER,
+                       CONSTRAINT fk_remote_build_servers_supported_os1 FOREIGN KEY ( supported_os_id ) REFERENCES supported_os ( id ) )#{post_fix}"
+       end
+
+
+       def self.load(ip, port, db)
+               saddr="#{ip}:#{port}"
+               row = db.select_one("SELECT remote_build_servers.*,supported_os.name as host_os_name FROM remote_build_servers, supported_os WHERE svr_addr='#{saddr}' and remote_build_servers.supported_os_id = supported_os.id")
+               if not row.nil? then
+                       return load_row(row)
+               end
+
+               return nil
+       end
+
+
+       def self.load_all(db)
+               result = []
+               rows = db.select_all("SELECT *,'' as host_os_name FROM remote_build_servers WHERE supported_os_id IS NULL
+                                                        UNION ALL
+                                                        SELECT remote_build_servers.*, supported_os.name as host_os_name FROM remote_build_servers, supported_os WHERE remote_build_servers.supported_os_id = supported_os.id")
+               rows.each do |row|
+                       result.push load_row(row)
+               end
+
+               return result
+       end
+
+
+       def self.load_row(row)
+               svr_ip,svr_port=row['svr_addr'].strip.split(":")
+               new_obj = new(svr_ip, svr_port, row['description'] )
+               new_obj.set_id( row['id'] )
+               new_obj.status = row['status']
+               new_obj.max_working_jobs =row['max_job_count']
+               new_obj.working_job_count =row['working_job_count']
+               new_obj.waiting_job_count =row['waiting_job_count']
+               new_obj.host_os = row['host_os_name']
+               return new_obj
+       end
+
+
+       def unload(db)
+               db.do("DELETE FROM remote_build_servers WHERE id=#{@id}")
+       end
+
+
+       def save(db)
+               saddr="#{@ip}:#{@port}"
+               db.do "INSERT INTO remote_build_servers (svr_addr,description) VALUES ('#{saddr}','#{@description}')"
+       end
+end
+
diff --git a/src/build_server/RemoteBuilder.rb b/src/build_server/RemoteBuilder.rb
new file mode 100644 (file)
index 0000000..78d3fa9
--- /dev/null
@@ -0,0 +1,259 @@
+=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"
+require "FileTransferViaFTP"
+require "FileTransferViaDirect"
+
+class RemoteBuilder
+       attr_accessor :id, :log
+
+       # initialize
+       def initialize( id, server,ftp_addr, ftp_port, ftp_username, ftp_passwd)
+               @id = id
+               @server = server
+               @addr = server.ip
+               @port = server.port
+               @ftp_addr = ftp_addr
+               @ftp_port = ftp_port
+               @ftp_username = ftp_username
+               @ftp_passwd = ftp_passwd
+               @log = DummyLog.new
+               @job = nil
+       end
+
+
+       # build_job
+       def build_job( job, local_pkgs )
+               # set job
+               @job = job
+               old_log = @log
+               @log = job.log
+
+               # build
+               ret = build(@job.get_project().repository, @job.source_path, @job.os,
+                                       @job.is_rev_build_check_job(), @job.git_commit, @job.no_reverse,
+                                       local_pkgs, @job.get_project().dist_name,"admin@user" )
+
+               # reset job
+               @job = nil
+               @log = old_log
+
+               # return
+               return ret
+       end
+
+
+       # build
+       def build( git_repos, source_path, os, is_rev_build, srcinfo, no_reverse, local_pkgs, dist_name, user_email )
+               @log.info( "Start to build on remote server...", Log::LV_USER )
+
+               # create unique dock number
+               dock = Utils.create_uniq_name()
+
+               # send local packages
+               begin
+                       @server.add_file_transfer()
+                       local_pkgs.each do |pkg_path|
+                               @log.info( "Sending file... : #{pkg_path}", Log::LV_USER )
+                               result = send_file_to_remote( pkg_path, dock )
+                               if not result then
+                                       @log.error( "File transfering failed!", Log::LV_USER )
+                                       @server.remove_file_transfer()
+                                       return false
+                               end
+                       end
+               ensure
+                       @server.remove_file_transfer()
+               end
+
+               # send build request
+               @log.info( "Sending build request to remote server...", Log::LV_USER )
+               result, result_files = send_build_request(git_repos, os, is_rev_build,
+                                                                                                 srcinfo, no_reverse, local_pkgs, dock, dist_name, user_email, @log.is_verbose)
+
+               @log.info( "Receiving log file from remote server...", Log::LV_USER )
+               if not receive_file_from_remote( "#{source_path}/../remote_log", dock ) then
+                       @log.warn( "File transfering failed! : remote_log", Log::LV_USER )
+               end
+
+               if not result then
+                       @log.error( "Building job on remote server failed!", Log::LV_USER )
+                       return false
+               end
+
+               # receive binary package
+               result_files.each do |file_name|
+                       @log.info( "Receiving file from remote server : #{file_name}", Log::LV_USER )
+                       result = receive_file_from_remote( "#{source_path}/#{file_name}", dock )
+                       if not result then
+                               @log.error( "File transfering failed! : #{file_name}", Log::LV_USER )
+                               return false
+                       end
+               end
+
+               return true
+       end
+
+
+       # upload binary packages that is need to be overwrite
+       # before remote package
+       protected
+       def send_file_to_remote(file_path, dock = "0")
+               # create client
+               client = BuildCommClient.create( @addr, @port, @log )
+               if client.nil? then
+                       @log.error( "Creating communication client failed!", Log::LV_USER)
+                       return false
+               end
+
+               # upload file
+               result = true
+               file_name = file_path.split("/")[-1]
+               msg = "UPLOAD|#{dock}"
+               if client.send( msg ) then
+                       if not @ftp_addr.nil? then
+                               transporter=FileTransferFTP.new(@log, @ftp_addr, @ftp_port, @ftp_username, @ftp_passwd)
+                       else
+                               transporter=FileTransferDirect.new(@log)
+                       end
+
+                       result=client.send_file( file_path, transporter )
+                       if not result then
+                               @log.error( "File uploading failed...#{file_name}", Log::LV_USER)
+                       end
+               end
+
+               #close connections
+               client.terminate
+
+               return result
+       end
+
+
+       # send build request
+       protected
+       def send_build_request(git_repos, os, is_rev_build, commit, no_reverse, local_pkgs, dock, dist_name, user_email, verbose)
+               result_files = []
+
+               client = BuildCommClient.create( @addr, @port, @log )
+               if client.nil? then
+                       @log.error( "Creating communication client failed!", Log::LV_USER)
+                       return false, result_files
+               end
+
+               # get local package names
+               local_pkg_names = local_pkgs.map { |path| File.basename(path) }
+
+               # send
+               #          0   | 1 |    2     |   3  | 4|  5  |     6    |    7    |    8     |   9   |   10   |   11    |  12  | 13 |  14
+               # format: BUILD|GIT|repository|passwd|os|async|no_reverse|dist_name|user_email|verbose|internal|rev-build|commit|pkgs|dock_num
+               # value : BUILD|GIT|repository|      |os|NO   |no_reverse|dist_name|user_email|verbose|YES     |rev-build|commit|pkgs|dock_num
+               result = true
+               commit = commit.nil? ? "":commit
+               pkg_list = local_pkg_names.join(",")
+               rev = is_rev_build ? "YES":"NO"
+               msg = "BUILD|GIT|#{git_repos}||#{os}|NO|#{no_reverse}|#{dist_name}|#{user_email}|#{verbose}|YES|#{rev}|#{commit}|#{pkg_list}|#{dock}"
+               result = client.send( msg )
+               if not result then
+                       @log.error( "Communication failed! #{client.get_error_msg()}", Log::LV_USER)
+                       return false, result_files
+               end
+
+               r_job_number = Regexp.new('Added new job "([^"]*)"')
+               error = false
+               result = client.read_lines do |l|
+                       # write log first
+                       @log.output( l.strip, Log::LV_USER)
+
+                       # set remote job id
+                       if not @job.nil? and  @job.remote_id.nil? and l =~ r_job_number then
+                               @job.remote_id = $1
+                       end
+
+                       # check build result
+                       if l.include? "Job is stopped by ERROR" or
+                               l.include? "Error:" then
+                               error = true
+                       end
+
+                       # gather result files if not reverse build
+                       if not is_rev_build and l =~ /Creating package file \.\.\. (.*)/ then
+                               file_name = $1
+                               result_files.push file_name
+                       end
+               end
+               if not result then
+                       @log.error( "Communication failed! #{client.get_error_msg()}", Log::LV_USER)
+               end
+               if error then result=false end
+
+               # close socket
+               client.terminate
+
+               return result, result_files
+       end
+
+
+       # receive binary package of remote server
+       protected
+       def receive_file_from_remote(file_path, dock = "0")
+               # create client
+               client = BuildCommClient.create( @addr, @port, @log )
+               if client.nil? then
+                       @log.error( "Creating communication client failed!", Log::LV_USER)
+                       return false
+               end
+
+               # download file
+               result = true
+               file_name = file_path.split("/")[-1]
+               msg = "DOWNLOAD|#{dock}|#{file_name}"
+               if client.send( msg ) then
+                       if not @ftp_addr.nil? then
+                               transporter=FileTransferFTP.new(@log, @ftp_addr, @ftp_port, @ftp_username, @ftp_passwd)
+                       else
+                               transporter=FileTransferDirect.new(@log)
+                       end
+                       result=client.receive_file(file_path, transporter)
+                       if not result then
+                               @log.error( "File downloading failed...#{file_name}", Log::LV_USER)
+                       end
+               end
+
+               #close connections
+               client.terminate
+
+               return result
+       end
+end
diff --git a/src/build_server/ReverseBuildChecker.rb b/src/build_server/ReverseBuildChecker.rb
new file mode 100644 (file)
index 0000000..49dde68
--- /dev/null
@@ -0,0 +1,217 @@
+=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 "JobLog.rb"
+require "PackageManifest.rb"
+
+class ReverseBuildChecker
+
+       # check
+       def ReverseBuildChecker.check( job, exit_on_error, override_os = nil )
+               log = job.log
+               job_os = (override_os.nil?) ? job.os : override_os
+
+               # start
+               log.info( "Checking reverse build dependency ...", Log::LV_USER)
+
+               # get target packages that be checked
+               bin_pkg_name_list = []
+               src_pkg_name_list = []
+               case job.type
+               when "BUILD"
+                       job.pkginfo.get_target_packages(job_os).each do |pkg|
+                               bin_pkg_name_list.push pkg.package_name
+                       end
+               when "REGISTER"
+                       if job.pkg_type == "BINARY" then
+                               bin_pkg_name_list.push job.pkg_name
+                       else
+                               src_pkg_name_list.push job.pkg_name
+                       end
+               end
+
+               # get reverse projects from build dependency
+               rev_pkgs = []
+               bin_pkg_name_list.each do |pkg_name|
+                       rev_pkgs += job.pkgsvr_client.get_reverse_build_dependent_packages(pkg_name, job_os)
+               end
+               src_pkg_name_list.each do |pkg_name|
+                       rev_pkgs += job.pkgsvr_client.get_reverse_source_dependent_packages(pkg_name)
+               end
+               rev_pkgs.uniq!
+               rev_projects = job.server.prjmgr.get_projects_from_pkgs(rev_pkgs, job.get_distribution_name())
+
+               # create reverse build job
+               rev_build_jobs = []
+               rev_projects.each do |p|
+                       rev_prj = p[0]
+                       rev_os = p[1]
+                       rev_ver = p[2]
+
+                       # if not "GIT" project, ignore it
+                       if rev_prj.type != "GIT" then next end
+
+                       # if job on resolve process, its unresolved project
+                       #of pending ancestor must be excluded.
+                       if job.type == "BUILD" and not job.pending_ancestor.nil? then
+                               found = false
+                               job.pending_ancestor.rev_fail_projects.each do  |fp|
+                                       f_prj = fp[0]
+                                       f_os =  fp[1]
+
+                                       if rev_prj == f_prj and rev_os == f_os then
+                                               found = true
+                                               break
+                                       end
+                               end
+                               if found then next end
+                       end
+
+                       # if this is sub job, all other sibling job must be excluded
+                       if job.is_sub_job? then
+                               job.get_parent_job().get_sub_jobs().each do |sub_job|
+                                       sub_prj = sub_job.get_project()
+                                       sub_os = sub_job.os
+                                       if rev_prj == sub_prj and rev_os == sub_os then
+                                               found = true
+                                               break
+                                       end
+                               end
+                               if found then next end
+                       end
+
+                       # create job
+                       new_job = rev_prj.create_new_job_from_version( rev_os, rev_ver )
+                       new_job.set_rev_build_check_job( job )
+
+                       # set user id
+                       new_job.user_id = job.user_id
+
+                       rev_build_jobs.push new_job
+               end
+
+               # reverse build
+               if rev_build_jobs.count > 0 then
+                       rev_prjs_msg = rev_build_jobs.map {|j| "#{j.get_project().name}(#{j.os})"}.join(", ")
+                       log.info( " * Will check reverse-build for projects: #{rev_prjs_msg}", Log::LV_USER)
+               end
+
+               # for all reverse job
+               rev_build_jobs.each do |rev_job|
+                       # add to job manager
+                       job.server.jobmgr.add_reverse_build_job(rev_job)
+                       log.info( " * Added new job for reverse-build ... #{rev_job.get_project().name}(#{rev_job.os}) (#{rev_job.id})", Log::LV_USER)
+               end
+
+               # wait for job finish
+               rev_build_finished = false
+               success_list = []
+               failure_list = []
+               cancel_other_jobs = false
+               while not rev_build_finished
+                       rev_build_finished = true
+                       rev_build_jobs.each do |rev_job|
+                               rev_prj = rev_job.get_project()
+                               rev_os = rev_job.os
+
+                               case rev_job.status
+                               when "ERROR", "CANCELED"
+                                       # add fail list
+                                       if not is_project_included?(failure_list, rev_prj, rev_os) then
+                                               log.info( " * Reverse-build FAIL ... #{rev_prj.name}(#{rev_os}) (#{rev_job.id})", Log::LV_USER)
+                                               failure_list.push [ rev_prj, rev_os ]
+                                               write_log_url(log, rev_job)
+                                       end
+
+                                       #  if "exist on error" cancel all other jobs
+                                       if exit_on_error then
+                                               cancel_other_jobs = true
+                                               rev_build_jobs.each do |j|
+                                                       if j.status != "ERROR" and j.status != "FINISHED" and
+                                                               j.status != "CANCELED" and j.cancel_state == "NONE" then
+
+                                                               j.cancel_state = "INIT"
+                                                       end
+                                               end
+                                               break
+                                       end
+                               when "FINISHED"
+                                       # add success list
+                                       if not success_list.include? rev_job then
+                                               log.info( " * Reverse-build OK ... #{rev_prj.name}(#{rev_os}) (#{rev_job.id})", Log::LV_USER)
+                                               success_list.push rev_job
+                                       end
+                               else
+                                       rev_build_finished = false
+                               end
+                       end
+
+                       sleep 1
+               end
+
+               # clean up all reverse build jobs
+               rev_build_jobs.each do |rev_job|
+                       if rev_job.status == "ERROR" or rev_job.status == "CANCELED" then
+                               rev_job.server.cleaner.clean_afterwards(rev_job.id)
+                       else
+                               rev_job.server.cleaner.clean(rev_job.id)
+                       end
+               end
+
+               return failure_list
+       end
+
+
+       private
+       def self.is_project_included?( prj_list, prj, os )
+               prj_list.each do |p|
+                       if p[0] == prj and p[1] == os then return true end
+               end
+
+               return false
+       end
+
+
+       # write web url for log
+       private
+       def self.write_log_url(log, job)
+               url,remote_url = job.get_log_url()
+               if not url.empty? then
+                       log.info( " ** Log1: #{url}", Log::LV_USER)
+               end
+               if not remote_url.empty? then
+                       log.info( " ** Log2: #{remote_url}", Log::LV_USER)
+               end
+       end
+end
index 4cfa7946818e5c29d2e0b9eb737e80f6afb6d53b..dc18da6f6697d66102a7dbc42627fecc86d91ec8 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  SocketJobRequestListener.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -27,10 +27,9 @@ Contributors:
 =end
 
 $LOAD_PATH.unshift File.dirname(__FILE__)
-require "GitBuildJob.rb"
-require "LocalBuildJob.rb"
 require "JobLog.rb"
 require "BuildComm.rb"
+require "BuildServerException.rb"
 
 
 class SocketJobRequestListener
@@ -40,14 +39,23 @@ class SocketJobRequestListener
                @parent_server = parent
                @thread = nil
                @finish_loop = false
+               @comm_server = nil
                @log = @parent_server.log
        end
 
        # start listening
        def start()
-               @thread = Thread.new {
-                       main()          
-               }
+               @thread = Thread.new do
+                       # make loop recover when unhandled exception occurred
+                       while not @finish_loop
+                               begin
+                                       main()
+                               rescue => e
+                                       @log.error e.message
+                                       @log.error e.backtrace.inspect
+                               end
+                       end
+               end
        end
 
 
@@ -56,36 +64,45 @@ class SocketJobRequestListener
        def stop_listening()
                @finish_loop = true
        end
-       
+
        private
 
-       # thread main  
+       # thread main
        def main()
                # server open
                begin
-                       server = BuildCommServer.new(@parent_server.port, @log)
+                       if not @parent_server.ftp_addr.nil? then
+                               ftp_url = Utils.generate_ftp_url(@parent_server.ftp_addr, @parent_server.ftp_port,
+                                                                                                @parent_server.ftp_username, @parent_server.ftp_passwd)
+                       else
+                               ftp_url = nil
+                       end
+                       cache_dir = "#{@parent_server.transport_path}/.cache"
+                       @comm_server = BuildCommServer.create(@parent_server.port, @log, ftp_url, cache_dir)
                rescue
                        @log.info "Server creation failed"
+                       puts "Server creation failed"
+                       @parent_server.stop
                        return
                end
 
                # loop
-               @log.info "Entering Control Listening Loop ... "        
+               @log.info "Entering Control Listening Loop ... "
                @finish_loop = false
-               server.wait_for_connection(@finish_loop) do |req|
-                               handle_job_request( req )
-               end     
+               @comm_server.wait_for_connection(@finish_loop) do |req|
+                       handle_job_request( req )
+               end
 
                # quit
-               server.terminate
+               @comm_server.terminate
        end
 
 
        # wait for job requests
        def wait_for_job_requests
                req_list = []
-               req_list.push @tcp_server.accept                
-               
+               req_list.push @tcp_server.accept
+
                return req_list
        end
 
@@ -94,15 +111,18 @@ class SocketJobRequestListener
        def handle_job_request( req )
 
                # read request
-               req_line = req.gets             
+               req_line = req.gets
                if req_line.nil? then return end
 
+               # accept
+               BuildCommServer.send_begin(req)
+
                # parse request
                cmd = ""
-               if req_line.split(",").count > 0 then
-                       cmd = req_line.split(",")[0].strip 
+               if req_line.split("|").count > 0 then
+                       cmd = req_line.split("|")[0].strip
                end
-               
+
                case  cmd
                when "BUILD"
                        handle_cmd_build( req_line, req )
@@ -110,142 +130,922 @@ class SocketJobRequestListener
                        handle_cmd_resolve( req_line, req )
                when "QUERY"
                        handle_cmd_query( req_line, req )
+               when "CANCEL"
+                       handle_cmd_cancel( req_line, req )
+               when "STOP"
+                       handle_cmd_stop( req_line, req )
+               when "UPGRADE"
+                       handle_cmd_upgrade( req_line, req )
+               when "FULLBUILD"
+                       handle_cmd_fullbuild( req_line, req )
+               when "REGISTER"
+                       handle_cmd_register( req_line, req )
+               when "DOWNLOAD"
+                       Thread.new do
+                               begin
+                                       handle_cmd_download( req_line, req )
+                               rescue => e
+                                       @log.error "Transfering file failed!"
+                                       @log.error e.message
+                                       @log.error e.backtrace.inspect
+                               end
+                       end
+               when "UPLOAD"
+                       Thread.new do
+                               begin
+                                       handle_cmd_upload( req_line, req )
+                               rescue => e
+                                       @log.error "Transfering file failed!"
+                                       @log.error e.message
+                                       @log.error e.backtrace.inspect
+                               end
+                       end
                else
-                       @log.info "Received Unknown REQ: #{req_line}" 
+                       @log.info "Received Unknown REQ: #{req_line}"
                        raise "Unknown request: #{req_line}"
                end
 
        end
 
 
-       # "BUILD"       
+       # "BUILD"
        def handle_cmd_build( line, req )
-               tok = line.split(",").map { |x| x.strip }
-               if tok.count < 4 then 
-                       @log.info "Received Wrong REQ: #{line}" 
-                       raise "Invalid request format is used: #{line}"
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_build_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
                end
 
-               case tok[1]
-               # BUILD,GIT,repos,commit,os,url,async
-               when "GIT"
-                       @log.info "Received BUILD GIT => #{tok[2]}"
+               @log.info "Handled REQ: #{line}"
+       end
 
-                       # check asynchronous job
-                       async = (not tok[6].nil? and tok[6]=="YES" ? true:false)        
-                       if async then
-                               new_job = GitBuildJob.new( tok[2], tok[3], tok[4], tok[5], [], @parent_server, nil, nil, false)
-                       else    
-                               new_job = GitBuildJob.new( tok[2], tok[3], tok[4], tok[5], [], @parent_server, nil, req, false)
-                       end
-                       BuildCommServer.send_begin(req)
 
-                       # start job. If log url is supported, show it
-                       if not @parent_server.job_log_url.empty? then
-                               new_job.log.info( "Added new job \"#{new_job.id}\"! Check following URL", Log::LV_USER)
-                               new_job.log.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER)
-                       else
-                               new_job.log.info( "Added new job \"#{new_job.id}\"!", Log::LV_USER)
+       def handle_cmd_build_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 3 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+               # check type
+               if tok[1] != "GIT" then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+               #          0  | 1 |     2      |  3   |  4    |  5  |     6    |    7    |   8      |   9   |   10   |    11   |  12  | 13 |   14
+               # Case1. BUILD|GIT|project_name|passwd|os_list|async|no_reverse|dist_name|user_email|verbose
+               # Case2. BUILD|GIT|git_repos   |      |os     |async|no_reverse|dist_name|user_email|verbose|internal|rev_build|commit|pkgs|dock_num
+
+               # parse
+               project_name_list = tok[2].split(",")
+               passwd_list = tok[3].split(",")
+               passwd = passwd_list[0]
+               os_list = tok[4].split(",")
+               async = tok[5].eql? "YES"
+               no_reverse = tok[6].eql? "YES"
+               dist_name = (not tok[7].nil? and not tok[7].empty?) ? tok[7].strip : ""
+               user_email = (not tok[8].nil? and not tok[8].empty?) ? tok[8].strip : ""
+               verbose = tok[9].eql? "YES"
+               is_internal = tok[10].eql? "YES"
+               rev_job = tok[11].eql? "YES"
+               git_commit = (not tok[12].nil? and not tok[12].empty?) ? tok[12] : nil
+               pkg_files = (not tok[13].nil? and not tok[13].empty?) ? tok[13].split(",") : []
+               dock_num = (not tok[14].nil? and not tok[14].empty?) ? tok[14].strip : "0"
+               if (dist_name.nil? or dist_name.empty?) then
+                       dist_name = @parent_server.distmgr.get_default_distribution_name()
+               end
+
+               # check distribution
+               check_distribution(dist_name, req)
+
+               # check supported os if not internal job
+               if not is_internal then
+                       os_list = check_supported_os( os_list , req )
+               end
+
+               # check user email
+               user_id = @parent_server.check_user_id_from_email( user_email )
+               if user_id == -1 then
+                       raise BuildServerException.new("ERR004"), user_email
+               end
+
+
+               # multi build job
+               if project_name_list.count > 1 or os_list.count > 1 then
+                       new_job_list = []
+                       i = 0
+                       project_name_list.each do |pname|
+                               if not passwd_list[i].nil? then passwd = passwd_list[i]
+                               else passwd = passwd_list[0] end
+                               check_build_project(pname,passwd,dist_name,req)
+                               if not check_project_user_id(pname,dist_name,user_id) then
+                                       raise BuildServerException.new("ERR005"), "#{user_email} -> #{pname}"
+                               end
+                               os_list.each do |os|
+                                       new_job = create_new_job( pname, os, dist_name )
+                                       if new_job.nil? then
+                                               @log.warn "\"#{pname}\" does not support #{os}"
+                                               next
+                                       else
+                                               new_job.user_id = user_id
+                                       end
+                                       new_job_list.push new_job
+                                       @log.info "Received a request for building this project : #{pname}, #{os}"
+                               end
+                               i = i + 1
                        end
 
-                       # if asynchronouse, quit connection
-                       if async then
-                               if not @parent_server.job_log_url.empty? then
-                                       req.puts ( "Info: Added new job \"#{new_job.id}\"! Check following URL")
-                                       req.puts ( "Info: * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log")
+                       if new_job_list.count > 1 then
+                               new_job = @parent_server.prjmgr.create_new_multi_build_job( new_job_list )
+                               if new_job.nil? then
+                                       raise BuildServerException.new("ERR006"),"Multi-Build job"
                                else
-                                       req.puts( "Info: Added new job \"#{new_job.id}\"!")
+                                       new_job.user_id = user_id
                                end
+                       elsif new_job_list.count == 1 then
+                               new_job = new_job_list[0]
+                       else
+                               raise BuildServerException.new("ERR006"),"No valid sub jobs in Multi-Build job"
+                       end
 
-                               BuildCommServer.send_end(req)
-                               BuildCommServer.disconnect(req)
-                       end     
+                       # transfered job
+               elsif is_internal then
+                       git_repos = project_name_list[0]
+                       os = os_list[0]
 
-                       # add
-                       @parent_server.add_job( new_job )
-
-               # BUILD,LOCAL,path,os,url
-               when "LOCAL"
-                       @log.info "Received BUILD LOCAL => #{tok[2]}" 
-                       
-                       BuildCommServer.send_begin(req)
-                       @parent_server.add_job( 
-                               LocalBuildJob.new( tok[2], tok[3], tok[4], [], @parent_server, nil, req, false))
+                       new_job = create_new_internal_job(git_repos, os, git_commit, pkg_files, dock_num, dist_name )
+                       if new_job.nil? then
+                               raise BuildServerException.new("ERR006"),"Transfered-Build job"
+                       else
+                               new_job.user_id = user_id
+                       end
+                       if rev_job then new_job.set_rev_build_check_job(nil) end
+
+                       # single job
+               elsif project_name_list.count == 1 and os_list.count == 1 then
+                       pname = project_name_list[0]
+                       os = os_list[0]
+
+                       check_build_project(pname,passwd,dist_name,req)
+                       if not check_project_user_id(pname,dist_name,user_id) then
+                               raise BuildServerException.new("ERR005"), "#{user_email} -> #{pname}"
+                       end
+                       new_job = create_new_job( pname, os, dist_name )
+                       if new_job.nil? then
+                               raise BuildServerException.new("ERR006"), "\"#{pname}\" does not support #{os} in #{dist_name}"
+                       else
+                               new_job.user_id = user_id
+                       end
                else
-                       @log.info "Received Wrong REQ: #{line}"
-                       raise "Invalid request format is used: #{line}"
-               end     
+                       raise BuildServerException.new("ERR006"), "Cannot find your project to build!"
+               end
+
+               # check reverse build
+               if no_reverse then new_job.set_no_reverse end
+
+               # create logger and set
+               if async then
+                       new_job.create_logger( nil, verbose)
+                       BuildCommServer.send(req,"Info: Added new job \"#{new_job.id}\" for #{new_job.os}!")
+                       if not @parent_server.job_log_url.empty? then
+                               BuildCommServer.send(req,"Info:  * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log")
+                       end
+                       BuildCommServer.send(req,"Info: Above job(s) will be processed asynchronously!")
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               else
+                       logger = new_job.create_logger( req, verbose)
+                       logger.info( "Added new job \"#{new_job.id}\" for #{new_job.os}!", Log::LV_USER)
+                       if not @parent_server.job_log_url.empty? then
+                               logger.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER)
+                       end
+               end
+
+               # add to job queue
+               if new_job.is_rev_build_check_job() then
+                       @parent_server.jobmgr.add_reverse_build_job( new_job )
+               else
+                       @parent_server.jobmgr.add_job( new_job )
+               end
        end
 
 
-       # "RESOLVE"     
-       def handle_cmd_resolve( line ,req)
-               tok = line.split(",").map { |x| x.strip }
-               if tok.count < 4 then 
-                       @log.info "Received Wrong REQ: #{line}" 
-                       raise "Invalid request format is used: #{line}"
+       def check_build_project(prj_name, passwd, dist_name, req)
+               # check project
+               prj = check_project_exist(prj_name, dist_name, req)
+
+               # check passwd
+               check_project_password(prj, passwd, req)
+
+               # check project type
+               if prj.type == "BINARY" then
+                       raise BuildServerException.new("ERR010"), prj.type
+               end
+       end
+
+
+       # "RESOLVE"
+       def handle_cmd_resolve( line, req )
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_resolve_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+
+               @log.info "Handled REQ: #{line}"
+       end
+
+
+       def handle_cmd_resolve_internal( line ,req)
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 3 then
+                       raise BuildServerException.new("ERR001"), line
                end
 
                case tok[1]
-               # RESOLVE,GIT,repos,commit,os,url
+                       # RESOLVE|GIT|project_name|passwd|os|async|dist_name|user_email|verbose
                when "GIT"
-                       @log.info "Received RESOLVE GIT => #{tok[2]}"
-
-                       BuildCommServer.send_begin(req)
-                       @parent_server.add_job( 
-                               GitBuildJob.new( tok[2], tok[3], tok[4], tok[5], [], @parent_server, nil, req, true))
-               # RESOLVE,LOCAL,path,os,url
-               when "LOCAL"
-                       @log.info "Received RESOLVE LOCAL => #{tok[2]}" 
-
-                       BuildCommServer.send_begin(req)
-                       @parent_server.add_job( 
-                               LocalBuildJob.new( tok[2], tok[3], tok[4], [], @parent_server, nil, req, true))
+
+                       # parse
+                       project_name=tok[2]
+                       passwd=tok[3]
+                       os=tok[4]
+                       async = tok[5].eql? "YES"
+                       dist_name = tok[6]
+                       user_email = (not tok[7].nil? and not tok[7].empty?) ? tok[7].strip : ""
+                       verbose = tok[8].eql? "YES"
+                       if (dist_name.nil? or dist_name.empty?) then
+                               dist_name = @parent_server.distmgr.get_default_distribution_name()
+                       end
+
+                       # check distribution
+                       check_distribution(dist_name, req)
+
+                       # check project
+                       prj = check_project_exist(project_name, dist_name, req)
+
+                       # check passwd
+                       check_project_password(prj, passwd, req)
+
+                       # check os
+                       os_list = check_supported_os( [os] , req )
+                       os = os_list[0]
+
+                       # check user email
+                       user_id = @parent_server.check_user_id_from_email( user_email )
+                       if user_id == -1 then
+                               raise BuildServerException.new("ERR004"), user_email
+                       end
+
+                       # check user accessable
+                       if not check_project_user_id(project_name,dist_name,user_id) then
+                               raise BuildServerException.new("ERR005"), "#{user_email} -> #{project_name}"
+                       end
+
+                       # create new job
+                       new_job = create_new_job( project_name, os, dist_name )
+                       if new_job.nil? then
+                               raise BuildServerException.new("ERR006"), "Resolve job #{project_name} #{os}"
+                       end
+                       @log.info "Received a request for resolving this project : #{project_name}, #{os}"
+
+                       new_job.user_id = user_id
+
+                       # resolve
+                       new_job.set_resolve_flag()
+
+                       # create logger and set
+                       if async then
+                               new_job.create_logger( nil, verbose)
+                               BuildCommServer.send(req,"Info: Added new job \"#{new_job.id}\" for #{new_job.os}!")
+                               if not @parent_server.job_log_url.empty? then
+                                       BuildCommServer.send(req,"Info:  * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log")
+                               end
+                               BuildCommServer.send(req,"Info: Above job(s) will be processed asynchronously!")
+                               BuildCommServer.send_end(req)
+                               BuildCommServer.disconnect(req)
+                       else
+                               logger = new_job.create_logger( req, verbose)
+                               logger.info( "Added new job \"#{new_job.id}\" for #{new_job.os}!", Log::LV_USER)
+                               if not @parent_server.job_log_url.empty? then
+                                       logger.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER)
+                               end
+                       end
+
+                       @parent_server.jobmgr.add_job( new_job )
                else
-                       @log.info "Received Wrong REQ: #{line}" 
-                       raise "Invalid request format is used: #{line}"
-               end     
+                       raise BuildServerException.new("ERR001"), line
+               end
        end
 
 
        # "QUERY"
        def handle_cmd_query( line, req )
-               tok = line.split(",").map { |x| x.strip }
-               if tok.count < 2 then 
-                       @log.info "Received Wrong REQ: #{line}" 
-                       raise "Invalid request format is used: #{line}"
+               begin
+                       handle_cmd_query_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
                end
-       
+       end
+
+
+       def handle_cmd_query_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 2 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
                case tok[1]
-               # QUERY,JOB
+
+                       # QUERY, FTP
+               when "FTP"
+                       if not @parent_server.ftp_addr.nil? then
+                               BuildCommServer.send(req,"#{@parent_server.ftp_addr},#{@parent_server.ftp_username},#{@parent_server.ftp_passwd}")
+                       else
+                               BuildCommServer.send(req,"NONE,NONE,NONE")
+                       end
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
+                       # QUERY,JOB
                when "JOB"
                        #puts "Received QUERY JOB"
 
-                       BuildCommServer.send_begin(req)
-                       for job in @parent_server.working_jobs
-                               BuildCommServer.send(req,"WORKING,#{job.id},#{job.pkginfo.packages[0].source}")
+                       # gather all jobs to show
+                       job_list = @parent_server.jobmgr.jobs + @parent_server.jobmgr.internal_jobs + @parent_server.jobmgr.reverse_build_jobs
+
+                       # send the status
+                       job_list.each do |job|
+                               status = job.status
+                               if status == "REMOTE_WORKING" then status = "REMOTE" end
+                               if job.cancel_state != "NONE" then status = "CANCEL" end
+
+                               case job.type
+                               when "BUILD"
+                                       if status == "PENDING" then
+                                               if job.pending_ancestor.nil? then
+                                                       ids = "/"
+                                               else
+                                                       ids = job.pending_ancestor.id
+                                               end
+                                               BuildCommServer.send(req,"#{status}:#{ids},#{job.id},#{job.get_project().name},#{job.os} #{job.progress},#{job.get_distribution_name}")
+                                       else
+                                               BuildCommServer.send(req,"#{status},#{job.id},#{job.get_project().name},#{job.os} #{job.progress},#{job.get_distribution_name}")
+                                       end
+                               when "REGISTER"
+                                       if job.pkg_type == "BINARY" and not job.get_project().nil? then
+                                               BuildCommServer.send(req,"#{status},#{job.id},#{job.get_project().name},#{job.os} #{job.progress},#{job.get_distribution_name}")
+                                       else
+                                               BuildCommServer.send(req,"#{status},#{job.id},#{job.pkg_name},#{job.get_distribution_name}")
+                                       end
+                               when "MULTIBUILD"
+                                       BuildCommServer.send(req,"#{status},#{job.id},MULTI-BUILD : #{job.get_sub_jobs().map{|x| x.id}.join(" ")},#{job.get_distribution_name}")
+                               end
                        end
-                       for job in @parent_server.waiting_jobs
-                               BuildCommServer.send(req,"WAITING,#{job.id},#{job.pkginfo.packages[0].source}")
+
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
+                       # QUERY,SYSTEM
+               when "SYSTEM"
+                       #puts "Received QUERY SYSTEM"
+
+                       BuildCommServer.send(req,"#{@parent_server.host_os},#{@parent_server.jobmgr.max_working_jobs}")
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               when "PROJECT"
+                       # print GIT projects
+                       sorted_list = @parent_server.prjmgr.get_all_projects_summary().sort { |x,y| x[:name] <=> y[:name] }
+                       sorted_list.select{|x| x[:ptype] == "GIT"}.each do |prj|
+                               BuildCommServer.send(req,"G,#{prj[:name]},#{prj[:dist_name]}")
+                       end
+                       # print BINARY projects
+                       sorted_list.select{|x| x[:ptype] == "BINARY"}.each do |prj|
+                               BuildCommServer.send(req,"B,#{prj[:name]},#{prj[:dist_name]}")
                        end
-                       for job in @parent_server.remote_jobs
-                               BuildCommServer.send(req,"REMOTE ,#{job.id},#{job.pkginfo.packages[0].source}")
+                       # print REMOTE project
+                       sorted_list.select{|x| x[:ptype] == "REMOTE"}.each do |prj|
+                               BuildCommServer.send(req,"R,#{prj[:name]},#{prj[:dist_name]}")
                        end
                        BuildCommServer.send_end(req)
                        BuildCommServer.disconnect(req)
 
-               # QUERY,SYSTEM
-               when "SYSTEM"
-                       #puts "Received QUERY SYSTEM" 
+               when "OS"
+                       # print GIT projects
+                       @parent_server.supported_os_list.each do |os_name|
+                               BuildCommServer.send(req,"#{os_name}")
+                       end
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
+               when "FRIEND"
+                       # print GIT projects
+                       @parent_server.remote_servers.each do |server|
+                               BuildCommServer.send(req,"#{server.status},#{server.host_os},#{server.waiting_job_count},#{server.working_job_count},#{server.max_working_jobs},#{server.get_file_transfer_cnt}")
+                       end
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+
+               else
+                       raise BuildServerException.new("ERR001"), line
+               end
+       end
+
+
+       # "CANCEL"
+       def handle_cmd_cancel( line, req )
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_cancel_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+
+               @log.info "Handled REQ: #{line}"
+       end
+
+
+       def handle_cmd_cancel_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 2 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+               cancel_job = nil
+
+               # check user email
+               user_id = @parent_server.check_user_id_from_email( tok[3] )
+               if user_id == -1 then
+                       raise BuildServerException.new("ERR004"), tok[3]
+               end
+
+               #CANCEL, JOB
+               (@parent_server.jobmgr.jobs + @parent_server.jobmgr.internal_jobs + @parent_server.jobmgr.reverse_build_jobs).each do |j|
+                       if "#{j.id}" == "#{tok[1]}" then
+                               cancel_job = j
+                               break
+                       end
+               end
+
+               if cancel_job.nil? then
+                       raise BuildServerException.new("ERR014"), "Job #{tok[1]} not found."
+               else
+                       if cancel_job.cancel_state == "NONE" then
+                               # check passwd
+                               if not @parent_server.jobmgr.is_user_accessable(cancel_job,user_id) then
+                                       raise BuildServerException.new("ERR014"), "Access denied #{tok[3]}"
+                               end
+                               if cancel_job.type == "MULTIBUILD" then
+                                       cancel_job.get_sub_jobs().select{|x| x.cancel_state == "NONE" }.each do |sub|
+                                               check_project_password( sub.get_project, tok[2], req)
+                                       end
+
+                                       BuildCommServer.send(req, "\"#{cancel_job.id}, #{cancel_job.get_sub_jobs().map{|x| x.id}.join(", ")}\" will be canceled")
+                                       cancel_job.cancel_state = "INIT"
+                                       BuildCommServer.send_end(req)
+                                       BuildCommServer.disconnect(req)
+                               else
+                                       prj = cancel_job.get_project()
+                                       if not prj.nil? then
+                                               check_project_password( prj, tok[2], req)
+
+                                               BuildCommServer.send(req, "\"#{cancel_job.id}\" will be canceled")
+                                               cancel_job.cancel_state = "INIT"
+                                               BuildCommServer.send_end(req)
+                                               BuildCommServer.disconnect(req)
+                                       else
+                                               raise BuildServerException.new("ERR014"), "No project infomation"
+                                       end
+                               end
+                       else
+                               raise BuildServerException.new("ERR014"), "Job already canceled."
+                       end
+               end
+       end
+
+
+       # "STOP"
+       def handle_cmd_stop( line, req )
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_stop_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+
+               @log.info "Handled REQ: #{line}"
+       end
+
+
+       def handle_cmd_stop_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 2 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+               if tok[1] != @parent_server.password then
+                       raise BuildServerException.new("ERR015"), ""
+               else
+                       BuildCommServer.send(req,"Server will be down!")
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+               if tok[1] == @parent_server.password then
+                       @parent_server.finish = true
+               end
+       end
+
 
-                       BuildCommServer.send_begin(req)
-                       BuildCommServer.send(req,"#{@parent_server.host_os},#{@parent_server.max_working_jobs}")
+       # "UPGRADE"
+       def handle_cmd_upgrade( line, req )
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_upgrade_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+
+               @log.info "Handled REQ: #{line}"
+       end
+
+
+       def handle_cmd_upgrade_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 2 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+               if tok[1] != @parent_server.password then
+                       raise BuildServerException.new("ERR015"), ""
+               else
+                       BuildCommServer.send(req,"Server will be upgraded!")
                        BuildCommServer.send_end(req)
                        BuildCommServer.disconnect(req)
+               end
+               if tok[1] == @parent_server.password then
+                       @parent_server.finish = true
+                       @parent_server.upgrade = true
+               end
+       end
+
+
+       # "FULLBUILD"
+       def handle_cmd_fullbuild( line, req )
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_fullbuild_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+
+               @log.info "Handled REQ: #{line}"
+       end
+
+
+       def handle_cmd_fullbuild_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 2 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+               server_passwd = tok[1]
+               dist_name = tok[2]
+               if (dist_name.nil? or dist_name.empty?) then
+                       dist_name = @parent_server.distmgr.get_default_distribution_name()
+               end
+
+               # check distribution
+               check_distribution(dist_name, req, true)
+
+               # check server password
+               if server_passwd != @parent_server.password then
+                       raise BuildServerException.new("ERR015"), ""
+               end
+
+               # create full build job
+               new_job = @parent_server.prjmgr.create_new_full_build_job(dist_name)
+
+               # set logger
+               new_job.create_logger( req ) 
+
+               # add to job
+               @parent_server.jobmgr.add_job( new_job )
+       end
+
+
+       # "REGISTER"
+       def handle_cmd_register( line, req )
+               @log.info "Received REQ: #{line}"
+
+               begin
+                       handle_cmd_register_internal( line, req )
+               rescue BuildServerException => e
+                       @log.error(e.message)
+                       BuildCommServer.send(req, e.err_message())
+                       BuildCommServer.send_end(req)
+                       BuildCommServer.disconnect(req)
+               end
+
+               @log.info "Handled REQ: #{line}"
+       end
+
+
+       def handle_cmd_register_internal( line, req )
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 4 then
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+               type = tok[1]
+
+               case type
+                       # REGISTER|BINARY-LOCAL|local_path|passwd|dist_name
+                       # REGISTER|SOURCE-LOCAL|local_path|passwd|dist_name
+               when "BINARY-LOCAL", "SOURCE-LOCAL"
+                       file_path = tok[2]
+                       dist_name = tok[4]
+                       if (dist_name.nil? or dist_name.empty?) then
+                               dist_name = @parent_server.distmgr.get_default_distribution_name()
+                       end
+
+                       # check distribution
+                       check_distribution(dist_name, req)
+
+                       new_job = @parent_server.jobmgr.create_new_register_job( file_path, dist_name )
+                       new_job.create_logger( req ) 
+
+                       # add
+                       @parent_server.jobmgr.add_job( new_job )
+
+                       # REGISTER|BINARY|filename|passwd|dock|dist_name|user_email|no_reverse
+               when "BINARY"
+                       # parse
+                       filename = tok[2]
+                       passwd = tok[3]
+                       dock = (tok[4].nil? or tok[4].empty?) ? "0" : tok[4].strip
+                       dist_name = tok[5]
+                       user_email = (tok[7].nil? or tok[7].empty?) ? "" : tok[6].strip
+                       no_reverse = tok[7].eql? "YES"
+
+                       if (dist_name.nil? or dist_name.empty?) then
+                               dist_name = @parent_server.distmgr.get_default_distribution_name()
+                       end
+
+                       # check distribution
+                       check_distribution(dist_name, req)
+
+                       # check project
+                       prj = check_project_for_package_file_name(filename, dist_name, req)
+
+                       # check user email
+                       user_id = @parent_server.check_user_id_from_email( user_email )
+                       if user_id == -1 then
+                               raise BuildServerException.new("ERR004"), user_email
+                       end
+
+                       if not check_project_pkg_name_user_id(filename, dist_name, user_id) then
+                               raise BuildServerException.new("ERR005"), "#{user_email} -> #{prj.name}"
+                       end
+
+                       # check passwd
+                       check_project_password(prj, passwd, req)
+
+                       # create new job
+                       @log.info "Received a request for uploading binaries : #{filename}"
+                       new_job = create_new_upload_job( prj.name, filename, dock, dist_name, req )
+                       if new_job.nil? then
+                               raise BuildServerException.new("ERR006"), "Register-job #{filename}, #{prj.name}, #{dist_name}"
+                       end
+
+                       new_job.user_id = user_id
+
+                       # check reverse build
+                       if no_reverse then new_job.set_no_reverse end
+
+                       # create logger and set
+                       logger = new_job.create_logger(req)
+
+                       # notify that job has been received
+                       logger.info( "Added new job \"#{new_job.id}\" for #{new_job.os}!", Log::LV_USER)
+                       if not @parent_server.job_log_url.empty? then
+                               logger.info( " * Log URL : #{@parent_server.job_log_url}/#{new_job.id}/log", Log::LV_USER)
+                       end
+
+                       # add
+                       @parent_server.jobmgr.add_job( new_job )
                else
-                       @log.info "Received Wrong REQ: #{line}" 
-                       raise "Invalid request format is used: #{line}"
+                       raise BuildServerException.new("ERR001"), line
+               end
+
+       end
+
+
+       # "UPLOAD"
+       def handle_cmd_upload( line, req )
+               @log.info "Received File transfer REQ : #{line}"
+
+               tok = line.split("|").map { |x| x.strip }
+               dock_num = (tok[1].nil? or tok[1].empty?) ? "0" : tok[1].strip
+
+               incoming_dir = "#{@parent_server.transport_path}/#{dock_num}"
+               if not File.exist? incoming_dir then FileUtils.mkdir_p incoming_dir end
+               @comm_server.receive_file( req, incoming_dir )
+               BuildCommServer.send_end(req)
+               BuildCommServer.disconnect(req)
+       end
+
+
+       # "DOWNLOAD"
+       # format = DOWNLOAD|dock_num|file_name
+       def handle_cmd_download( line, req )
+               @log.info "Received File transfer REQ : #{line}"
+               tok = line.split("|").map { |x| x.strip }
+               dock_num = (tok[1].nil? or tok[1].empty?) ? "0" : tok[1].strip
+               file_name = tok[2]
+
+               @log.info "Received a request for download file : #{file_name}"
+               outgoing_dir = "#{@parent_server.transport_path}/#{dock_num}"
+               @log.info "Sending requested file...: #{file_name}"
+               @comm_server.send_file(req, "#{outgoing_dir}/#{file_name}")
+               # remove file if "dock" defined
+               if dock_num != "0" and File.exist? "#{outgoing_dir}/#{file_name}" then
+                       @log.info "Removing requested file...: #{file_name}"
+                       FileUtils.rm_rf "#{outgoing_dir}/#{file_name}"
+                       if Utils.directory_emtpy?(outgoing_dir) then
+                               FileUtils.rm_rf "#{outgoing_dir}"
+                       end
                end
+
+               BuildCommServer.send_end(req)
+               BuildCommServer.disconnect(req)
+       end
+
+
+       private
+       def check_project_user_id(project_name, dist_name, user_id)
+               return @parent_server.prjmgr.get_project_accessable(project_name, dist_name, user_id)
+       end
+
+       private
+       def check_project_exist(project_name, dist_name, req)
+               prj = @parent_server.prjmgr.get_project(project_name, dist_name)
+               if prj.nil? then
+                       raise BuildServerException.new("ERR009"), "#{project_name} on #{dist_name}"
+               end
+
+               return prj
+       end
+
+       private
+       def check_project_pkg_name_user_id(file_name, dist_name, user_id)
+               # get package name
+               new_name = file_name.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+               pkg_name = new_name.split(",")[0]
+               return @parent_server.prjmgr.get_project_pkg_name_accessable(pkg_name, dist_name, user_id)
        end
 
+       private
+       def check_project_for_package_file_name(filename, dist_name, req)
+               # get package name
+               new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+               pkg_name = new_name.split(",")[0]
+
+               prj = @parent_server.prjmgr.get_project_from_package_name(pkg_name, dist_name)
+               if prj.nil? then
+                       raise BuildServerException.new("ERR013"), "#{pkg_name} #{dist_name}"
+               end
+
+               return prj
+       end
+
+
+       private
+       def check_project_password(prj, passwd, req)
+
+               if prj.is_passwd_set?  then
+                       if passwd.nil? or passwd.empty? then
+                               raise BuildServerException.new("ERR011"), "Use -w option to input your project password"
+                       end
+
+                       if not prj.passwd_match?(passwd) then
+                               raise BuildServerException.new("ERR012"), ""
+                       end
+               end
+       end
+
+
+       private
+       def check_distribution(dist_name, req, only_exist = false)
+               dist = @parent_server.distmgr.get_distribution(dist_name)
+               if dist.nil? then
+                       raise BuildServerException.new("ERR002"), dist_name
+               elsif dist.status != "OPEN" and not only_exist then
+                       raise BuildServerException.new("ERR008"), dist_name
+               end
+       end
+
+
+       private
+       def check_supported_os(os_list, req)
+
+               # check if supported os list contain at least one OS
+               if @parent_server.supported_os_list.empty? then
+                       raise BuildServerException.new("ERR007"), ""
+               end
+
+               result = []
+               os_list.each do |os|
+                       if os == "all" or os == "*" then
+                               result = result + @parent_server.supported_os_list
+
+                       elsif os == "default" then
+                               os =  @parent_server.supported_os_list[0]
+                               result.push os
+                               @log.info "The default OS \"#{os}\" is used as target OS"
+
+                       elsif os.include? "*" then
+                               reg_os = os.gsub("*","[a-zA-Z0-9.]*")
+                               @parent_server.supported_os_list.each do |svr_os|
+                                       matches = svr_os.match("#{reg_os}")
+                                       if not matches.nil? and matches.size == 1 and
+                                               matches[0] == svr_os then
+                                               result.push svr_os
+                                       end
+                               end
+                       elsif @parent_server.supported_os_list.include?(os) then
+                               result.push os
+                       else
+                               msgs = "#{os}\n\tSupported OS list.\n"
+                               @parent_server.supported_os_list.each do |os_name|
+                                       msgs += "\t * #{os_name}\n"
+                               end
+                               raise BuildServerException.new("ERR003"),msgs
+                       end
+               end
+
+               result.uniq!
+               if result.empty? then
+                       raise BuildServerException.new("ERR003"), "There is no OS name matched."
+               end
+
+               return result
+       end
+
+
+       private
+       def create_new_job( project_name, os, dist_name )
+               return @parent_server.prjmgr.create_new_job(project_name, os, dist_name)
+       end
+
+
+       private
+       def create_new_upload_job( project_name, filename, dock, dist_name, req)
+
+               return @parent_server.prjmgr.get_project(project_name, dist_name).create_new_job(filename, dock)
+       end
+
+
+       private
+       def create_new_internal_job( git_repos, os, git_commit, pkg_files, dock_num, dist_name )
+               prj = @parent_server.prjmgr.get_git_project( git_repos, dist_name )
+               if prj.nil? then
+                       prj = @parent_server.prjmgr.create_unnamed_git_project( git_repos, dist_name )
+               end
+               new_job = prj.create_new_job(os)
+               new_job.set_internal_job( dock_num )
+               new_job.git_commit = git_commit
+               incoming_dir = "#{@parent_server.transport_path}/#{dock_num}"
+               pkg_files.each do |file|
+                       new_job.add_external_package( file )
+               end
+
+               return new_job
+       end
 end
index a9e672cff3a347c13fed5903560e0e5031357079..386cb944680807e8dff2b497399505a7fde0a4b3 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  Builder.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -36,22 +36,29 @@ require "log"
 
 class Builder
        private_class_method :new
-       attr_accessor :id, :pkgserver_url, :log
+       attr_accessor :id, :pkgserver_url, :log, :buildroot_dir, :cache_dir
 
        CONFIG_ROOT = Utils::HOME + "/.build_tools/builder"
        @@instance_map = {}
 
        # initialize
-       def initialize (id, pkgserver_url, log_path)
+       def initialize (id, pkgserver_url, log_path, buildroot_dir, cache_dir)
                @id = id
                @pkgserver_url = pkgserver_url
                @host_os = Utils::HOST_OS
-               @log = Log.new(log_path)
+               @buildroot_dir = buildroot_dir
+               @cache_dir = cache_dir
+               @job = nil
+               if not log_path.nil? then
+                       @log = Log.new(log_path)
+               else
+                       @log = DummyLog.new
+               end
        end
 
-       
+
        # create
-       def self.create (id, pkgserver_url, log_path)
+       def self.create (id, pkgserver_url, log_path, buildroot_dir, cache_dir)
 
                # check builder config root
                check_builder_config_root
@@ -61,8 +68,24 @@ class Builder
                        FileUtils.rm_rf "#{CONFIG_ROOT}/#{id}"
                end
 
+               # create buildroot if not set
+               if buildroot_dir.nil? then
+                       buildroot_dir = "#{CONFIG_ROOT}/#{id}/buildroot"
+                       if not File.exist? buildroot_dir then
+                               FileUtils.mkdir_p buildroot_dir
+                       end
+               end
+
+               # create cachedir if not set
+               if cache_dir.nil? then
+                       cache_dir = "#{CONFIG_ROOT}/#{id}/build_cache"
+                       if not File.exist? cache_dir then
+                               FileUtils.mkdir_p cache_dir
+                       end
+               end
+
                # create new instance and return it
-               @@instance_map[id] = new( id, pkgserver_url, log_path )
+               @@instance_map[id] = new( id, pkgserver_url, log_path, buildroot_dir, cache_dir )
 
                # write config
                write_builder_config( @@instance_map[id] )
@@ -83,16 +106,28 @@ class Builder
        end
 
 
+       def self.exist?( id )
+               # check builder config root
+               check_builder_config_root
+
+               # check id
+               if File.exist? "#{CONFIG_ROOT}/#{id}" then
+                       return true
+               else
+                       return false
+               end
+       end
+
        # get
        def self.get( id )
 
                # check instance first
                if not @@instance_map[id] == nil
-                       return @@instance_map[id] 
+                       return @@instance_map[id]
                end
 
-               # check builder config 
-               if not File.exist? "#{CONFIG_ROOT}/#{id}/builder.cfg" 
+               # check builder config
+               if not File.exist? "#{CONFIG_ROOT}/#{id}/builder.cfg"
                        raise RuntimeError, "The builder \"#{id}\" does not exist."
                end
 
@@ -106,68 +141,109 @@ class Builder
        # clean
        def clean( src_path )
 
-               build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot"
+               return clean_project_directory( src_path, nil )
+       end
 
-               # create pkginfo
-        pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
 
-               # make clean
-           for pkg in pkginfo.packages
-                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.linux"
-                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.windows"
-                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.darwin"
-               end
-               env_def = 
-                       "SRCDIR=\"#{src_path}\" "
-        build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} clean"
-               if not Utils.execute_shell_with_log( build_command, @log )
-                       @log.error( "Failed on clean script", Log::LV_USER )
-                       return false
-               end
+       # build_job
+       def build_job( job, clean, local_pkgs, is_local_build )
+               # set job
+               @job = job
+               old_log = @log
+               @log = job.log
 
-               return true
+               # build
+               ret = build(job.source_path, job.os, clean, local_pkgs, is_local_build)
+
+               # reset job
+               @job = nil
+               @log = old_log
+
+               # return
+               return ret
        end
 
 
        # build
-       def build( src_path, os, clean, reverse_dep_check, pending_pkg_dir_list, ignore_rev_dep_build_list )
+       def build( src_path, os, clean, local_pkgs, is_local_build )
 
                # create pkginfo
-        pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
+               if not File.exist? "#{src_path}/package/pkginfo.manifest" then
+                       @log.error( "The \"package/pkginfo.manifest\" file does not exist!", Log::LV_USER)
+                       return false
+               end
 
-               # check there are packages which can be built
-               if not pkginfo.package_exist?(os, Utils::HOST_OS ) then
-                       @log.error( "There are no packages which can be built on this host OS: #{Utils::HOST_OS}")
-                       @log.error( " * Check \"Build-host-os\" in pkginfo.manifest" )
+               # read pkginfo
+               begin
+                       pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
                        return false
                end
 
-               # set build root
-               if clean then
-                       build_root_dir = "#{CONFIG_ROOT}/#{@id}/temp_root"
-               else
-                       build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot"
+               # set default build os
+               build_host_os = @host_os
+
+               # check there are packages which can be built
+               if not pkginfo.package_exist?(os, build_host_os )  then
+                       if is_local_build and File.exist? "#{src_path}/package/pkginfo.manifest.local" then
+                               begin
+                                       pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest.local")
+                               rescue => e
+                                       @log.error( e.message, Log::LV_USER)
+                                       return false
+                               end
+                               if not pkginfo.package_exist?(os, build_host_os ) then
+
+                                       @log.error( "This project does not support a build on this host OS: #{build_host_os}")
+                                       @log.error( " * Check \"Build-host-os\" in pkginfo.manifest or pkginfo.manifest.local" )
+
+                                       return false
+                               end
+                       else
+                               @log.error( "This project does not support a build on this host OS: #{build_host_os}")
+                               @log.error( " * Check \"Build-host-os\" in pkginfo.manifest" )
+
+                               return false
+                       end
+               end
+
+               #set up change log
+               change_log = {}
+               begin
+                       change_log = Parser.read_changelog "#{src_path}/package/changelog" if File.exist? "#{src_path}/package/changelog"
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       return false
                end
 
-        FileUtils.mkdir_p build_root_dir
+               if not change_log.empty? and pkginfo.packages[0].change_log.empty? then
+                       pkginfo.packages.each {|pkg| pkg.change_log = change_log}
+               end
 
-        local_pkg_list = []
-        pending_pkg_dir_list.each do |dir|
-            local_pkg_list += Dir.entries(dir).select{|e| e =~ /\.zip$/}.map{|p| dir + "/" + p}
-        end
+               # set build root
+               build_root_dir = @buildroot_dir
+               if not File.exist? build_root_dir then
+                       FileUtils.mkdir_p build_root_dir
+               end
 
                # create client
                @log.info( "Downloding client is initializing...", Log::LV_USER)
-               cl = Client.new(@pkgserver_url, build_root_dir, @log)
-               if clean then 
+               cl = Client.new(@pkgserver_url, build_root_dir, @log)
+               if clean then
                        cl.clean(true)
                end
-        cl.update
+
+               # get local repository path list
+               repos_paths = []
+               local_pkgs.each do  |path|
+                       repos_paths.push File.dirname(path)
+               end
+               repos_paths.uniq!
 
                # install build dependencies
-        package_overwrite_list = []
                @log.info( "Installing dependent packages...", Log::LV_USER)
-               pkginfo.get_build_dependencies( os, @host_os ).each do |dep|
+               pkginfo.get_build_dependencies( os ).each do |dep|
                        if dep.target_os_list.count != 0 then
                                dep_target_os = dep.target_os_list[0]
                        else
@@ -175,75 +251,54 @@ class Builder
                        end
                        @log.info( " * #{dep.package_name}", Log::LV_USER)
 
-            # get local dependent package 
-            pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$")
-            package_overwrite_list += local_pkg_list.select{|l| l =~ pkgexp}
+                       # get local dependent package
+                       pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$")
+                       local_dep_pkgs = local_pkgs.select{|l| l =~ pkgexp}
 
-            if not cl.install(dep.package_name, dep_target_os, true, false)  then
-                               @log.error( "Installing \"#{dep.package_name}\" failed!", Log::LV_USER)
-                               return false
+                       # install package from remote package server
+                       if local_dep_pkgs.empty? then
+                               if not cl.install(dep.package_name, dep_target_os, true, false)  then
+                                       @log.error( "Installing \"#{dep.package_name}\" failed!", Log::LV_USER)
+                                       return false
+                               end
+                       else
+                               local_dep_pkgs.each do |l|
+                                       @log.info( "Installing  local package...#{l}", Log::LV_USER)
+                                       if not File.exist? l then
+                                               @log.error( "File not found!: #{l}", Log::LV_USER )
+                                       end
+                                       cl.install_local_pkg(l,true,false, repos_paths)
+                               end
                        end
                end
 
-        # overwrite local dependent packages
-        package_overwrite_list.each do |l|
-            cl.install_local_pkg(l,false)
-        end 
-
                @log.info( "Downloading dependent source packages...", Log::LV_USER)
-        pkginfo.get_source_dependencies(os,@host_os).each do |dep|
-            @log.info( " * #{dep.package_name}", Log::LV_USER)
-
-            if cl.download_dep_source(dep.package_name).nil? then
-                @log.error( "Downloading \"#{dep.package_name}\" failed!", Log::LV_USER)
-                return false
-            end
-        end
-
-               # make clean
-               @log.info( "Make clean...", Log::LV_USER)
-           for pkg in pkginfo.packages
-                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.linux"
-                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.windows"
-                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.darwin"
-               end 
-
-               # convert path if windows
-               if Utils::HOST_OS == "windows" then
-                       build_root_dir = Utils.get_unix_path( build_root_dir )
+               src_archive_list = []
+               pkginfo.get_source_dependencies(os,build_host_os).each do |dep|
+                       src_archive_list.push dep.package_name
                end
-               env_def = 
-                       "BUILD_TARGET_OS=#{os} \
-                        SRCDIR=\"#{src_path}\" \
-                        ROOTDIR=\"#{build_root_dir}\" "
-        build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} clean"
-
-               if not Utils.execute_shell_with_log( build_command, @log )
-                       @log.error( "Failed on clean script", Log::LV_USER)
-                       return false
+               src_archive_list.uniq!
+               src_archive_list.each do |archive_name|
+                       @log.info( " * #{archive_name}", Log::LV_USER)
+                       if cl.download_dep_source(archive_name).nil? then
+                               @log.error( "Downloading \"#{archive_name}\" failed!", Log::LV_USER)
+                               return false
+                       end
                end
 
-               # make source package
-               @log.info( "Make source package...", Log::LV_USER)
-        build_command = "cd \"#{src_path}\";tar czf #{pkginfo.packages[0].source}_#{pkginfo.packages[0].version}.tar.gz --exclude=.git *"
-               if not Utils.execute_shell_with_log( build_command, @log )
-                       @log.error( "Failed on tar script", Log::LV_USER)
+               # make clean
+               @log.info( "Make clean...", Log::LV_USER)
+               if not clean_project_directory( src_path, os ) then
                        return false
                end
 
-               # execute build script
                @log.info( "Make build...", Log::LV_USER)
-        build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} build"
-               if not Utils.execute_shell_with_log( build_command, @log )
-                       @log.error( "Failed on build script", Log::LV_USER)
+               if not execute_build_command("build", src_path, build_root_dir, os, pkginfo.get_version) then
                        return false
                end
-               
                # execute install script
                @log.info( "Make install...", Log::LV_USER)
-        build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} install"
-               if not Utils.execute_shell_with_log( build_command, @log )
-                       @log.error( "Failed on build script", Log::LV_USER)
+               if not execute_build_command("install", src_path, build_root_dir, os, pkginfo.get_version) then
                        return false
                end
 
@@ -256,37 +311,12 @@ class Builder
 
                # zip
                @log.info( "Zipping...", Log::LV_USER)
-               make_zip(pkginfo,os,src_path)
-               
-               # check reverse dependecy if needed
-               if reverse_dep_check then
-                       if not check_reverse_build_dependency_fail_list(src_path, os, cl, true, ignore_rev_dep_build_list).empty? then
-                               return false
-                       end
+               if not make_zip(pkginfo,os,src_path) then
+                       @log.error( "Creating packages failed!", Log::LV_USER)
+                       return false
                end
-               return true
-       end
 
-    def build_resolve(src_path, os, pending_pkg_dir_list, ignore_rev_dep_build_list)
-        # clean build
-        if not build(src_path, os, true, false, pending_pkg_dir_list, ignore_rev_dep_build_list) then 
-            return nil
-        end
-        # init client
-        build_root_dir = "#{CONFIG_ROOT}/#{@id}/temp_root"
-        cl = Client.new(@pkgserver_url, build_root_dir, @log)
-        # rev build
-        return check_reverse_build_dependency_fail_list(src_path, os, cl, false, ignore_rev_dep_build_list )
-    end 
-
-
-       # reset
-       def reset()
-               build_root_dir = "#{CONFIG_ROOT}/#{@id}/buildroot"
-        temp_dir = cl.location
-        cl.location = build_root_dir
-        cl.clean(true)
-        cl.location = temp_dir
+               return true
        end
 
 
@@ -307,15 +337,17 @@ class Builder
        def self.write_builder_config( obj )
                # create config folder
                builder_dir = "#{CONFIG_ROOT}/#{obj.id}"
-               FileUtils.mkdir_p( "#{builder_dir}" )
+               if not File.exist? builder_dir then
+                       FileUtils.mkdir_p( "#{builder_dir}" )
+               end
 
                # write configuration
                File.open( "#{builder_dir}/builder.cfg", "w" ) do |f|
                        f.puts "ID=#{obj.id}"
                        f.puts "PSERVER_URL=#{obj.pkgserver_url}"
                        f.puts "LOG-PATH=#{obj.log.path}"
+                       f.puts "CACHE-DIR=#{obj.cache_dir}"
                end
-               puts "#{builder_dir}/builder.cfg"
        end
 
 
@@ -325,166 +357,169 @@ class Builder
 
                # read configuration
                builder_dir = "#{CONFIG_ROOT}/#{id}"
-        log_path = nil
+               log_path = nil
+               cache_dir = "#{CONFIG_ROOT}/#{id}/build_cache"
+               buildroot_dir = "#{CONFIG_ROOT}/#{id}/buildroot"
                File.open( "#{builder_dir}/builder.cfg", "r" ) do |f|
                        f.each_line do |l|
                                if l.start_with?("PSERVER_URL=")
-                    pkgserver_url = l.split("=")[1].strip
-                elsif l.start_with?("LOG-PATH=")
-                    log_path = l.split("=")[1].strip 
-                    log_path = nil if log_path == "STDOUT" 
+                                       pkgserver_url = l.split("=")[1].strip
+                               elsif l.start_with?("LOG-PATH=")
+                                       log_path = l.split("=")[1].strip
+                                       log_path = nil if log_path == "STDOUT"
+                               elsif l.start_with?("CACHE-DIR=")
+                                       cache_dir = l.split("=")[1].strip
+                               elsif l.start_with?("BUILDROOT-DIR=")
+                                       buildroot_dir = l.split("=")[1].strip
                                else
-                                       next    
-                               end 
+                                       next
+                               end
                        end
                end
 
-        if log_path.empty? then log_path = nil end
-               # create object & return it
-               return new( id, pkgserver_url, log_path )
-       end
+               if log_path.empty? then log_path = nil end
 
-
-       # check reverse build dependency
-       def check_reverse_build_dependency_fail_list( parent_path, os, pkg_cl, immediately, ignore_rev_dep_build_list )
-               @log.info( "Checking reverse build dependency ...", Log::LV_USER)
-
-        reverse_fail_list = []
-
-               # install newly packages
-               for path in Dir.glob("*_*_#{os}.zip")
-                       # install
-                       pkg_cl.install_local_pkg( path, false )
-               end             
-
-               # get reverse-dependent source-codes
-        pkginfo = PackageManifest.new("#{parent_path}/package/pkginfo.manifest")
-               pkg_list = [] 
-               for pkg in pkginfo.packages
-                       pkg_list = pkg_list + pkg_cl.get_reverse_build_dependent_packages(pkg.package_name, os)
-            @log.info( "Extract reverse build dependency #{pkg.package_name} ...", Log::LV_USER)
-               end
-        pkg_list -= ignore_rev_dep_build_list
-               pkg_list.uniq!
-               
-               # download sources
-               src_path_hash = {}
-               pkg_list.each do |pkg|
-                       # download
-                       src_path = pkg_cl.download_source(pkg, os)
-            @log.info( "Downloaded #{pkg} source package to #{src_path}", Log::LV_USER)
-
-            if src_path_hash[src_path].nil? then 
-                src_path_hash[src_path] = [pkg]
-            else 
-                src_path_hash[src_path] += [pkg]
-            end 
-        end
-        src_path_list = src_path_hash.keys
-
-               # add jobs for building reverse-dependent
-               src_path_list.each do |path|
-                       # extract source package to test path
-                       @log.info( " * Extracting source ... #{path}", Log::LV_USER)
-                       test_src_path = "#{parent_path}/tmp_build"
-                       FileUtils.mkdir_p test_src_path
-                       Utils.execute_shell("cd \"#{test_src_path}\";tar xf #{path}")
-                       
-                       # build
-                       @log.info( " * Building source ... ", Log::LV_USER)
-                       result = build_test_with_pkg_client( pkg_cl, test_src_path, os, parent_path )
-                       FileUtils.rm_rf test_src_path
-                       if not result  then 
-                reverse_fail_list += src_path_hash[path]
-                               @log.error( "Build \"#{src_path_hash[path].join(", ")}\" test failed", Log::LV_USER)
-                if immediately then 
-                    return reverse_fail_list
-                end 
-            end
-        end
-
-               return reverse_fail_list.uniq
+               # create object & return it
+               return new( id, pkgserver_url, log_path, buildroot_dir, cache_dir )
        end
 
 
-       # build test
-       def build_test_with_pkg_client( pkg_cl, src_path, os,  parent_path)
+       # execute build command
+       def execute_build_command( target, src_path, build_root_dir, os, version )
 
-        local_pkg_list = []
-        local_pkg_list += Dir.entries(parent_path).select{|e| e =~ /\.zip$/}.map{|p| parent_path + "/" + p}
+               # get category
+               os_category = Utils.get_os_category( os )
 
-               # create pkginfo
-        pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
+               # convert directory format when windows
+               if Utils.is_windows_like_os( @host_os ) then
+                       src_path2 = Utils.get_unix_path( src_path )
+               else
+                       src_path2 = src_path
+               end
 
-               # install build dependencies
-        package_overwrite_list = []
-               pkginfo.get_build_dependencies(os,@host_os).each do |dep|
-                       if dep.target_os_list.count != 0 then
-                               dep_target_os = dep.target_os_list[0]
-                       else
-                               dep_target_os = os
+               env_def =
+                       "BUILD_TARGET_OS=#{os} \
+TARGET_OS=#{os} \
+TARGET_OS_CATEGORY=#{os_category} \
+SRCDIR=\"#{src_path2}\" \
+ROOTDIR=\"#{build_root_dir}\" \
+VERSION=\"#{version}\" "
+
+               # check script file
+               script_file = "#{src_path}/package/build.#{@host_os}"
+               if not File.exist? script_file then
+                       if Utils.is_linux_like_os( @host_os ) then
+                               script_file = "#{src_path}/package/build.linux"
+                       elsif Utils.is_windows_like_os( @host_os ) then
+                               script_file = "#{src_path}/package/build.windows"
+                       elsif Utils.is_macos_like_os( @host_os ) then
+                               script_file = "#{src_path}/package/build.macos"
+                       end
+                       # check old script file
+                       if not File.exist? script_file then
+                               @log.error( "The script file not found!: \"package/build.#{@host_os}\"", Log::LV_USER)
+                               return false
                        end
+               end
 
-            # get local dependent package 
-            pkgexp = Regexp.new("\/#{dep.package_name}_.*_#{dep_target_os}\.zip$")
-            package_overwrite_list += local_pkg_list.select{|l| l =~ pkgexp}
+               # read build script
+               # this will ignore last lines without block
+               contents = []
+               File.open( script_file, "r" ) do |f|
+                       lines = []
+                       f.each_line do |l|
+                               lines.push l
+                               if l.start_with? "}" then
+                                       contents = contents + lines
+                                       lines = []
+                               end
+                       end
+               end
 
-            pkg_cl.install(dep.package_name, dep_target_os, true, false)
-               end     
+               # generate shell script
+               File.open( "#{src_path}/.build.sh", "w" ) do |f|
+                       f.puts "#!/bin/sh -xe"
+                       contents.each do |l|
+                               f.puts l
+                       end
 
-        # overwrite local dependent packages
-        package_overwrite_list.each do |l|
-            @log.info( "Package overwrite ..#{l}", Log::LV_USER)
-            pkg_cl.install_local_pkg(l,false)
-        end 
+                       case target
+                       when "clean"
+                               f.puts " "
+                       when "build"
+                               f.puts " "
+                       when "build_cache"
+                               f.puts "CACHEDIR=${PKG_CACHE_DIR}/$(cache_key)"
+                       when "save_cache"
+                               f.puts "rm -rf ${PKG_CACHE_DIR}/*"
+                               f.puts "CACHEDIR=${PKG_CACHE_DIR}/$(cache_key)"
+                               f.puts "mkdir -p ${CACHEDIR}"
+                       when "install"
+                               f.puts " "
+                       else
+                               @log.warn( "Wrong build-target is used: \"#{target}\"", Log::LV_USER)
+                               return false
+                       end
+                       f.puts "#{target}"
+                       f.puts "echo \"success\""
+               end
+               Utils.execute_shell( "chmod +x #{src_path}/.build.sh" )
+               build_command = "cd \"#{src_path}\";" + env_def + "./.build.sh"
 
-               # source download
-               pkginfo.get_source_dependencies(os,@host_os).each do |dep|
-            pkg_cl.download_dep_source(dep.package_name)
+               # execute script
+               status = nil
+               if not @job.nil? then
+                       pid, status = @job.execute_command( build_command )
+               else
+                       pid, status = Utils.execute_shell_with_log( build_command, @log.path )
                end
 
-               # execute build script
-               build_root_dir = pkg_cl.location
-               env_def = 
-                       "BUILD_TARGET_OS=#{os} \
-                        SRCDIR=\"#{src_path}\" \
-                        ROOTDIR=\"#{build_root_dir}\" "
-        build_command = "cd \"#{src_path}\";" + env_def + "./package/build.#{@host_os} build"
-               if not Utils.execute_shell_with_log( build_command, @log ) then
-                       @log.error( "Failed on build script", Log::LV_USER)
+               if not status.nil? and status.exitstatus != 0 then
+                       @log.error( "Failed on build script: \"#{target}\"", Log::LV_USER)
                        return false
                else
+                       Utils.execute_shell( "rm -rf #{src_path}/.build.sh" )
                        return true
                end
-
        end
 
 
-       # write pkginfo.manifest and install/remove script
+       # write pkginfo.manifest
        def     write_pkginfo_files(pkginfo,os,src_path)
-               for pkg in pkginfo.packages
+               # get category
+               os_category = Utils.get_os_category( os )
+
+               pkginfo.packages.each do |pkg|
                        # skip if not support the target os
-                       if not pkg.os.include? os
+                       if not pkg.os_list.include? os
                                next
                        end
 
-                       # install script files
-                       copy_post_install_script(pkg,os,src_path);
-                       copy_post_remove_script(pkg,os,src_path);
+                       # install/remove script files
+                       if not copy_post_install_script(pkg,os,src_path) then return false end
+                       if not copy_post_remove_script(pkg,os,src_path) then return false end
 
                        # write manifest file
                        install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}"
-                       
+
                        # if there is no intall directory, error
                        if not File.exist? install_dir then
-                               @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
-                               @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
-                               return false
+                               install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
+
+                               if not File.exist? install_dir then
+                                       @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
+                                       @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
+                                       @log.error( "Host OS name : #{@host_os}", Log::LV_USER)
+                                       @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER)
+                                       return false
+                               end
                        end
-               
-                       # write pkginfo.manifest        
+
+                       # write pkginfo.manifest
                        File.open("#{install_dir}/pkginfo.manifest", "w") do |f|
-                               pkg.print_to_file_with_os( f, os )
+                               f.puts pkg
+                               f.puts ""
+                               f.puts pkg.change_log_string
                        end
                end
 
@@ -494,74 +529,219 @@ class Builder
 
        # copy post-install script
        def     copy_post_install_script(pkg,os,src_path)
-               
+
                tar = nil
+               src = nil
 
-               if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{os}"
-                       src = "#{src_path}/package/#{pkg.package_name}.install.#{os}"
-               else
-                       src = nil
+               # get category
+               os_category_list = []
+               pkg.os_list.each do |cos|
+                       os_category_list.push Utils.get_os_category(cos)
+               end
+
+               # check compatable os
+               (pkg.os_list + os_category_list).uniq.each do |cos|
+                       if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{cos}" then
+                               if src.nil? then
+                                       src = "#{src_path}/package/#{pkg.package_name}.install.#{cos}"
+                               else
+                                       @log.error( "compatable package can have only one install script\n but you have another availabe install scripts", Log::LV_USER)
+                                       @log.error( " * package/#{File.basename src}", Log::LV_USER)
+                                       @log.error( " * package/#{pkg.package_name}.install.#{cos}", Log::LV_USER)
+                                       return false
+                               end
+                       end
+               end
+
+               install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}"
+
+               # if there is no intall directory, error
+               if not File.exist? install_dir then
+                       os_category = Utils.get_os_category( os )
+                       install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
+
+                       if not File.exist? install_dir then
+                               @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
+                               @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
+                               @log.error( "Host OS name : #{@host_os}", Log::LV_USER)
+                               @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER)
+                               return false
+                       end
                end
 
                if not src.nil? then
-                       if os == "linux" or os == "darwin" then
-                               tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/install.sh"
-                       elsif os == "windows" then
-                               tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/install.BAT"
+                       if Utils.is_unix_like_os( os ) then
+                               tar = "#{install_dir}/install.sh"
+                       elsif Utils.is_windows_like_os( os) then
+                               tar = "#{install_dir}/install.BAT"
                        else
                                puts "Unknown OS: #{os} "
-                               return
+                               return true
                        end
 
                        FileUtils.cp(src, tar)
-               end     
-       
-               return
+               end
+
+               return true
        end
 
 
        # copy post-remove script
        def     copy_post_remove_script(pkg,os,src_path)
-               
+
                tar = nil
+               src = nil
 
-               if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{os}"
-                       src = "#{src_path}/package/#{pkg.package_name}.remove.#{os}"
-               else
-                       src = nil
+               # get category
+               os_category_list = []
+               pkg.os_list.each do |cos|
+                       os_category_list.push Utils.get_os_category(cos)
+               end
+
+               # check compatable os
+               (pkg.os_list + os_category_list).uniq.each do |cos|
+                       if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{cos}" then
+                               if src.nil? then
+                                       src = "#{src_path}/package/#{pkg.package_name}.remove.#{cos}"
+                               else
+                                       @log.error( "compatable package can have only one remove script but you have another availabe remove scripts", Log::LV_USER)
+                                       @log.error( " * package/#{File.basename src}", Log::LV_USER)
+                                       @log.error( " * package/#{pkg.package_name}.remove.#{cos}", Log::LV_USER)
+                                       return false
+                               end
+                       end
+               end
+
+               install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}"
+
+               # if there is no intall directory, error
+               if not File.exist? install_dir then
+                       os_category = Utils.get_os_category( os )
+                       install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
+
+                       if not File.exist? install_dir then
+                               @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
+                               @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
+                               @log.error( "Host OS name : #{@host_os}", Log::LV_USER)
+                               @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER)
+                               return false
+                       end
                end
 
                if not src.nil?
-            puts "------> #{src}"
-                       if os == "linux" or os == "darwin" then
-                               tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/remove.sh"
-                puts "-0--\==> #{tar}"
-                       elsif os == "windows" then
-                               tar = "#{src_path}/package/#{pkg.package_name}.package.#{os}/remove.BAT"
+                       if Utils.is_unix_like_os( os ) then
+                               tar = "#{install_dir}/remove.sh"
+                       elsif Utils.is_windows_like_os( os) then
+                               tar = "#{install_dir}/remove.BAT"
                        else
                                puts "Unknown OS: #{os} "
-                               return
+                               return true
                        end
 
                        FileUtils.cp(src, tar)
-               end     
+               end
+               return true
        end
 
 
        # create package file
        def     make_zip(pkginfo,os,src_path)
-               for pkg in pkginfo.packages
+               # get category
+               os_category = Utils.get_os_category( os )
+
+               pkginfo.packages.each do |pkg|
                        # skip if not support the target os
-                       if not pkg.os.include? os
+                       if not pkg.os_list.include? os
                                next
                        end
 
                        # cd install dir
                        install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}"
-                       
-                       # zip   
+                       if not File.exist? install_dir then
+                               install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
+
+                               if not File.exist? install_dir then
+                                       @log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
+                                       @log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
+                                       @log.error( "Host OS name : #{@host_os}", Log::LV_USER)
+                                       @log.error( "It caused wrong pkginfo.manifest, pkginfo.manifest.local or build script", Log::LV_USER)
+                                       return false
+                               end
+                       end
+
+                       # zip
                        @log.info( "Creating package file ... #{pkg.package_name}_#{pkg.version}_#{os}.zip", Log::LV_USER)
-                       Utils.execute_shell("cd \"#{install_dir}\"; zip -r -y #{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip *")
+                       cmd = "cd \"#{install_dir}\"; zip -r -y #{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip *"
+                       @log.info( cmd )
+                       if not @job.nil? then
+                               @job.execute_command( cmd )
+                       else
+                               Utils.execute_shell_with_log(cmd, @log.path)
+                       end
+
+                       if not File.exist? "#{src_path}/#{pkg.package_name}_#{pkg.version}_#{os}.zip" then
+                               return false
+                       end
                end
+               return true
+       end
+
+
+       # clean the temporary directory for packaged
+       def clean_project_directory(src_path, target_os = nil)
+
+               # if os is not set, use host os instead
+               if target_os.nil? then target_os = @host_os end
+
+               # convert path if windows
+               if Utils.is_windows_like_os(@host_os) then
+                       build_root_dir = Utils.get_unix_path( @buildroot_dir )
+               else
+                       build_root_dir = @buildroot_dir
+               end
+
+               # create pkginfo
+               begin
+                       pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest")
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       return false
+               end
+
+               # get category
+               # make clean
+               pkginfo.packages.each do |pkg|
+                       os =  pkg.os
+                       os_category = Utils.get_os_category( os )
+
+                       if File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}" then
+                               FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}"
+                       elsif File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" then
+                               FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
+                       end
+               end
+
+               # clean local-only package's directory
+               if File.exist? "#{src_path}/package/pkginfo.manifest.local" then
+                       begin
+                               pkginfo = PackageManifest.new("#{src_path}/package/pkginfo.manifest.local")
+                       rescue => e
+                               @log.error( e.message, Log::LV_USER)
+                               return false
+                       end
+                       pkginfo.packages.each do |pkg|
+                               os =  pkg.os
+                               os_category = Utils.get_os_category( os )
+
+                               if File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}" then
+                                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{pkg.os}"
+                               elsif File.exist? "#{src_path}/package/#{pkg.package_name}.package.#{os_category}" then
+                                       FileUtils.rm_rf "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
+                               end
+                       end
+               end
+
+               # execute
+               return execute_build_command("clean", src_path, build_root_dir, target_os, pkginfo.get_version)
        end
 end
index 31611fcf37f46c895bb5d81430b923e303ce6bc4..7a2646b37e847f7e52ae8ffe286ee47dee7adbd1 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- CleanOptionParser.rb 
+
+ CleanOptionParser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -28,20 +28,30 @@ Contributors:
 
 require 'optparse'
 require 'logger'
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+require "utils"
 
 def parse()
 
-    #option parsing 
-    option = {}
-    optparse = OptionParser.new do |opts|
-        opts.banner = "Usage: pkg-clean"
-        opts.on('-h','--help', 'display this information') do 
-            puts opts
-            exit
-        end 
-    end 
-
-    optparse.parse!
-   return option
-end 
+       #option parsing
+       option = {}
+       optparse = OptionParser.new(nil, 32, ' '*8) do |opts|
+               opts.banner = "Clean the package service command-line tool." + "\n" \
+                       + "\n" + "Usage: pkg-clean [-h] [-v]" + "\n" \
+                       + "\n" + "Options:" + "\n"
+
+               opts.on('-h','--help', 'display help') do
+                       puts opts
+                       exit
+               end
+
+               opts.on('-v','--version', 'display version') do
+                       puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
+                       exit
+               end
+       end
+
+       optparse.parse!
+
+       return option
+end
index 05888f0254485cdfaad3ec38148bdf0efdaea67e..e8bab2c8cdf6c6470db685cc15a55e6091ab0db9 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  optionparser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -28,35 +28,53 @@ Contributors:
 
 require 'optparse'
 require 'logger'
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+require "utils"
 
 def parse()
 
-    #option parsing 
-    option = {}
-    optparse = OptionParser.new do |opts|
-        opts.banner = "Usage: pkg-build -u <remote_package_server_url> -o <os> -c -h"
-        opts.on('-u','--url <remote_package_server_url>', 'remote package server url') do |url|
-            option[:url] = url
-        end 
-        option[:os] = nil
-        opts.on('-o','--os <os>', 'operating system ') do |os|
-            option[:os] = os
-        end 
-        option[:clean] = false
-        opts.on('-c','--clean', 'clean build') do 
-            option[:clean] = true
-        end 
-        option[:rev] = false
-        opts.on('-r','--rev', 'reverse build dependency check') do 
-            option[:rev] = true
-        end 
-        opts.on('-h','--help', 'display this information') do 
-            puts opts
-            exit
-        end 
-    end 
-
-    optparse.parse!
-   return option
-end 
+       #option parsing
+       option = {}
+       optparse = OptionParser.new do |opts|
+               opts.banner = "Build and packaging service command-line tool." + "\n" \
+                       + "\n" + "Usage: pkg-build -u <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[:os] = nil
+               opts.on('-o','--os <os>', 'operating system ') do |os|
+                       option[:os] = os
+               end
+
+               option[:clean] = false
+               opts.on('-c','--clean', 'clean build') do
+                       option[:clean] = true
+               end
+
+               option[:rev] = false
+               #opts.on('-r','--rev', 'reverse build dependency check') do
+               #    option[:rev] = true
+               #end
+
+               opts.on('-h','--help', 'display help') do
+                       puts opts
+                       exit
+               end
+
+               opts.on('-v','--version', 'display version') do
+                       puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
+                       exit
+               end
+       end
+
+       optparse.parse!
+
+       if option[:url].nil? or option[:url].empty? then
+               raise ArgumentError, "Usage: pkg-build -u <package server url> [-o <os>] [-c] [-h]"
+       end
+
+       return option
+end
diff --git a/src/common/Action.rb b/src/common/Action.rb
new file mode 100644 (file)
index 0000000..ed18fb0
--- /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
diff --git a/src/common/BuildComm.rb b/src/common/BuildComm.rb
new file mode 100644 (file)
index 0000000..f80a9e2
--- /dev/null
@@ -0,0 +1,657 @@
+require "socket"
+
+=begin
+
+ BuildComm.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__)
+require "log"
+require 'timeout'
+require "net/ftp"
+require 'thread'
+require "FileTransferViaFTP"
+require "FileTransferViaDirect"
+
+ATTEMPTS = ["first", "second", "third"]
+
+class BuildCommServer
+       VERSION = "1.7.0"
+
+       private_class_method :new
+
+       def initialize(port, log, ftp_url, cache_dir)
+               @port = port
+               @log = log
+               @ftp_url = ftp_url
+               @cache_dir = cache_dir
+               @tcp_server = TCPServer.open( port )
+               @download_cache_mutex = Mutex.new
+       end
+
+       def self.create(port, log, ftp_url=nil, cache_dir=nil)
+               # checking port is  available
+               if port_open? port then
+                       raise "Port \"#{port}\" is already in use."
+               end
+
+               if log.nil? then
+                       log = DummyLog.new
+               end
+
+               # create cache dir if not nil
+               if not cache_dir.nil? and not File.exist? cache_dir then
+                       FileUtils.mkdir_p cache_dir
+               end
+
+               return new(port, log, ftp_url, cache_dir)
+       end
+
+
+       # wait for connection and handle request
+       def wait_for_connection(quit_loop)
+               while( not quit_loop )
+                       req = @tcp_server.accept
+
+                       begin
+                               yield req if block_given?
+                       rescue
+                               @log.error $!
+                               @log.error "Caught a connection exception"
+                               req.close
+                       end
+               end
+       end
+
+
+       # terminate
+       def terminate
+               @tcp_server.close()
+       end
+
+
+       # send_begin
+       def self.send_begin( req )
+               send( req, "=BEGIN,#{VERSION}")
+       end
+
+
+       def self.send_end( req )
+               send( req, "=END")
+       end
+
+
+       def self.send_chk( req )
+               send( req, "=CHK" )
+       end
+
+
+       def self.send( req, line )
+               begin
+                       if not req.nil? then
+                               req.puts line
+                       end
+               rescue
+                       raise "Connection is closed"
+               end
+       end
+
+
+       def send_file(req, src_file)
+               begin
+                       if not File.exist? src_file then
+                               @log.error "\"#{src_file}\" file does not exist"
+                               req.puts "ERROR"
+                               return false
+                       end
+
+                       req.puts "READY"
+                       @log.info "Ready to send file"
+
+                       while line = req.gets()
+                               tok = line.split(",").map { |x| x.strip }
+                               cmd = tok[0].strip
+                               case cmd
+                               when "CHECK_TRANSPORTER"
+                                       type = tok[1].strip
+                                       case type
+                                       when "DIRECT"
+                                               transporter = FileTransferDirect.new(@log)
+                                       when "FTP"
+                                               if not @ftp_url.nil? then
+                                                       url_contents = Utils.parse_ftpserver_url(@ftp_url)
+                                                       ip = url_contents[0]
+                                                       port = url_contents[1]
+                                                       username = url_contents[2]
+                                                       passwd = url_contents[3]
+                                                       transporter = FileTransferFTP.new(@log, ip, port, username, passwd)
+                                               else
+                                                       transporter = FileTransferFTP.new(@log)
+                                               end
+                                       else
+                                               req.puts "ERROR"
+                                               @log.error "Unsupported transporter type! : #{type}"
+                                               return false
+                                       end
+
+                                       req.puts "TRANSPORTER_OK"
+
+                                       if not transporter.send_file( src_file, req, false ) then
+                                               return false
+                                       else
+                                               return true
+                                       end
+
+                               else
+                                       @log.warn "Unhandled message: #{line}"
+                               end
+                       end
+
+               rescue => e
+                       puts "[BuildCommServer] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return false
+               end
+
+               return true
+       end
+
+
+       # NOTE. dst_file can be directory
+       def receive_file(req, dst_file)
+               begin
+                       req.puts "READY"
+                       @log.info "Ready to receive file"
+
+                       while line = req.gets()
+                               tok = line.split(",").map { |x| x.strip }
+                               cmd = tok[0].strip
+                               case cmd
+                               when "CHECK_CACHE"
+                                       file_name = tok[1]
+                                       file_size = tok[2].to_i
+                                       checksum = tok[3]
+
+                                       # check download cache
+                                       if File.exist? dst_file and File.directory? dst_file then
+                                               target_file = File.join(dst_file,file_name)
+                                       else
+                                               target_file = dst_file
+                                       end
+                                       if not @cache_dir.nil? and
+                                               check_download_cache( target_file, file_size, checksum ) then
+
+                                               @log.info "Download cache hit! Copied from cache.: #{file_name}"
+                                               req.puts "CACHED"
+                                       else
+                                               @log.info "Cached file not found!#{file_name}"
+                                               req.puts "NOT_CACHED"
+                                       end
+
+                               when "CHECK_TRANSPORTER"
+                                       type = tok[1].strip
+                                       case type
+                                       when "DIRECT"
+                                               transporter = FileTransferDirect.new(@log)
+                                       when "FTP"
+                                               if not @ftp_url.nil? then
+                                                       url_contents = Utils.parse_ftpserver_url(@ftp_url)
+                                                       ip = url_contents[0]
+                                                       port = url_contents[1]
+                                                       username = url_contents[2]
+                                                       passwd = url_contents[3]
+                                                       transporter = FileTransferFTP.new(@log, ip, port, username, passwd)
+                                               else
+                                                       transporter = FileTransferFTP.new(@log)
+                                               end
+                                       else
+                                               req.puts "ERROR"
+                                               @log.error "Unsupported transporter type! : #{type}"
+                                               return false
+                                       end
+
+                                       req.puts "TRANSPORTER_OK"
+
+                                       if not transporter.receive_file( dst_file, req, false ) then
+                                               return false
+                                       end
+
+                                       # add to cache
+                                       if not @cache_dir.nil? then
+                                               add_download_cache(target_file)
+                                       end
+                                       break
+
+                               else
+                                       @log.warn "Unhandled message: #{line}"
+                               end
+                       end
+               rescue => e
+                       puts "[BuildCommServer] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return false
+               end
+
+               return true
+       end
+
+
+       def self.disconnect( req )
+               begin
+                       req.close
+               rescue
+               end
+       end
+
+       def self.port_open?( port )
+               Timeout::timeout(1) do
+                       begin
+                               TCPSocket.new("127.0.0.1",port).close
+                               true
+                       rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
+                               false
+                       end
+               end
+       rescue Timeout::Error
+               false
+       end
+
+
+       private
+       def check_download_cache(dst_file, file_size, checksum )
+               file_name = File.basename(dst_file)
+               cache_file = "#{@cache_dir}/#{file_name}"
+
+               @download_cache_mutex.synchronize do
+                       found = false
+                       # check file exist
+                       if File.exist? cache_file and
+                               File.size(cache_file) == file_size and
+                               Utils.checksum(cache_file) == checksum then
+
+                               # if hit , touch and copy
+                               FileUtils.touch cache_file
+                               FileUtils.copy_file(cache_file, dst_file)
+
+                               found = true
+                       end
+
+                       # refresh cache dir
+                       curr_time = Time.now
+                       Dir.entries(@cache_dir).each do  |fname|
+                               if fname == "." or fname == ".." then next end
+                               file_path = "#{@cache_dir}/#{fname}"
+                               if File.mtime(file_path) + 3600 < curr_time then
+                                       FileUtils.rm_rf file_path
+                               end
+                       end
+
+                       return found
+               end
+       end
+
+
+       private
+       def add_download_cache(dst_file)
+               file_name = File.basename(dst_file)
+               cache_file = "#{@cache_dir}/#{file_name}"
+               @download_cache_mutex.synchronize do
+                       # copy & touch
+                       FileUtils.copy_file(dst_file, cache_file)
+                       FileUtils.touch cache_file
+               end
+       end
+end
+
+
+class BuildCommClient
+       VERSION = "1.7.0"
+       FIRST_REPONSE_TIMEOUT = 120
+
+       private_class_method :new
+
+       def initialize(socket, log)
+               @log = log
+               @socket = socket
+               @error_msg = ""
+       end
+
+
+       # create
+       # if sec 0 or nil then not set timeout. it's timeout spec
+       def self.create(ip, port, log = nil, sec = 5)
+               # open socket
+               socket = nil
+               begin
+                       timeout(sec) do
+                               socket = TCPSocket.open( ip, port )
+                       end
+               rescue Timeout::Error
+                       return nil
+               rescue
+                       # unknown exception
+                       return nil
+               end
+
+               # refused
+               if socket.nil? then
+                       return nil
+               end
+
+               if log.nil? then
+                       log = DummyLog.new
+               end
+
+               return new(socket, log)
+       end
+
+
+       def get_error_msg()
+               return @error_msg
+       end
+
+
+       def set_error_msg( msg )
+               @error_msg = msg
+       end
+
+
+       def send( msg )
+               if @socket.nil? then 
+                       @error_msg = "Connection is not available!"
+                       return false 
+               end
+
+               @socket.puts( msg )
+               return true
+       end
+
+
+       def print_stream
+
+               begin
+                       l = nil
+                       timeout(FIRST_REPONSE_TIMEOUT) do
+                               l = @socket.gets()
+                       end
+
+                       if l.nil? then
+                               @error_msg = "Connection closed or no more message"
+                               return false
+                       end
+
+                       # check protocol
+                       if not protocol_matched? l.strip then
+                               @error_msg = "Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!"
+                               return false
+                       end
+
+                       # get contents
+                       while line = @socket.gets()
+                               if line.strip == "=END" then break end
+                               if line.strip == "=CHK" then next end
+                               # print
+                               puts line.strip
+                       end
+               rescue Timeout::Error
+                       @error_msg = "Connection timed out!"
+                       return false
+
+               rescue => e
+                       @error_msg = e.message
+                       return false
+               end
+
+               return true
+       end
+
+
+       # handle
+       def read_lines
+
+               begin
+                       # get first line
+                       l = nil
+                       timeout(FIRST_REPONSE_TIMEOUT) do
+                               l = @socket.gets()
+                       end
+
+                       if l.nil? then
+                               @error_msg = "Connection closed or No more message"
+                               return false
+                       end
+
+                       # check protocol
+                       if not protocol_matched? l.strip then
+                               @error_msg = "Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!"
+                               return false
+                       end
+
+                       # get contents
+                       result = true
+                       while line = @socket.gets()
+                               if line.strip == "=END" then break end
+                               if line.strip == "=CHK" then next end
+
+                               # execute
+                               yield line.strip if block_given?
+                       end
+               rescue Timeout::Error
+                       @error_msg = "Connection timed out!"
+                       return false
+
+               rescue => e
+                       @error_msg = e.message
+                       return false
+               end
+
+               return true
+       end
+
+
+       # return result
+       def receive_data
+               result = []
+
+               begin
+                       l = nil
+                       timeout(FIRST_REPONSE_TIMEOUT) do
+                               l = @socket.gets()
+                       end
+
+                       if l.nil? then
+                               @error_msg = "Connection closed or No more message"
+                               return nil
+                       end
+
+                       # check protocol
+                       if not protocol_matched? l.strip then
+                               @error_msg = "Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!"
+                               return nil
+                       end
+
+                       # get contents
+                       while line = @socket.gets()
+                               if line.strip == "=END" then break end
+                               if line.strip == "=CHK" then next end
+                               # print
+                               result.push line.strip
+                       end
+
+               rescue Timeout::Error
+                       @error_msg = "Connection timed out!"
+                       return nil
+
+               rescue => e
+                       @error_msg = e.message
+                       return nil
+               end
+
+               return result
+       end
+
+
+       def send_file(src_file, transporter )
+
+               result = true
+               begin
+                       l = @socket.gets()
+                       if l.nil? then
+                               @log.error "[BuildCommClient] Connection refused"
+                               return false
+                       end
+
+                       # check protocol
+                       if not protocol_matched? l.strip then
+                               @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!"
+                               return false
+                       end
+
+                       while line = @socket.gets()
+                               cmd = line.split(",")[0].strip
+                               case cmd
+                               when "READY"
+                                       @log.info "Server is ready!"
+                                       file_name = File.basename(src_file)
+                                       file_size = File.size(src_file)
+                                       checksum = Utils.checksum(src_file)
+                                       send "CHECK_CACHE,#{file_name},#{file_size},#{checksum}"
+
+                               when "CACHED"
+                                       @log.info "Server already has cached file"
+                                       break
+
+                               when "NOT_CACHED"
+                                       @log.info "Server does not have cached file"
+                                       send "CHECK_TRANSPORTER,#{transporter.type}"
+
+                               when "TRANSPORTER_OK"
+                                       if not transporter.send_file( src_file, @socket, true ) then
+                                               result = false
+                                       else
+                                               @log.info "Sending file succeeded!"
+                                       end
+
+                               when "TRANSPORTER_FAIL"
+                                       @log.warn "Server does not support transporter type: #{transporter.type}"
+                                       result = false
+
+                               when "ERROR"
+                                       result = false
+
+                               when "=END"
+                                       break
+
+                               else
+                                       @log.warn "Unhandled message: #{line}"
+                               end
+                       end
+               rescue => e
+                       puts "[BuildCommClient] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return false
+               end
+
+               return result
+       end
+
+
+       # return file
+       def receive_file(dst_file, transporter)
+               result = true
+
+               begin
+                       l = @socket.gets()
+
+                       if l.nil? then
+                               @log.error "[BuildCommClient] Connection refused"
+                               return false
+                       end
+
+                       # check protocol
+                       if not protocol_matched? l.strip then
+                               @log.error "[BuildCommClient] Comm. Protocol version is mismatched! #{VERSION}. Upgrade your DIBS client!"
+                               return false
+                       end
+
+                       while line = @socket.gets()
+                               cmd = line.split(",")[0].strip
+                               case cmd
+                               when "READY"
+                                       @log.info "Server is ready!"
+                                       send "CHECK_TRANSPORTER,#{transporter.type}"
+
+                               when "TRANSPORTER_OK"
+                                       if not transporter.receive_file( dst_file, @socket, true ) then
+                                               result = false
+                                       else
+                                               @log.info "Receiving file succeeded!"
+                                       end
+
+                               when "ERROR"
+                                       result = false
+
+                               when "=END"
+                                       break
+
+                               else
+                                       @log.warn "Unhandled message: #{line}"
+                               end
+                       end
+               rescue => e
+                       puts "[BuildCommServer] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return false
+               end
+
+               return result
+       end
+
+
+       def terminate
+               @socket.close
+       end
+
+
+       private
+
+
+       # check protocol
+       def protocol_matched?(l)
+
+               version = ( l.split(",")[1].nil? ? "1.0.0" : l.split(",")[1] )
+               if not l.start_with? "=BEGIN" or
+                       version.nil? or version != VERSION then
+                       return false
+               else
+                       return true
+               end
+       end
+end
diff --git a/src/common/FileTransferViaDirect.rb b/src/common/FileTransferViaDirect.rb
new file mode 100644 (file)
index 0000000..d45f79e
--- /dev/null
@@ -0,0 +1,138 @@
+=begin
+
+ FileTransferViaDirect.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 'socket'
+require 'log'
+
+class FileTransferDirect
+       attr_accessor :type
+
+       def initialize(logger)
+               @type = "DIRECT"
+
+               if not logger.nil? then
+                       @log = logger
+               else
+                       @log = DummyLog.new
+               end
+       end
+
+
+       def send_file( src_file, conn, is_client=true )
+
+               filename = File.basename(src_file)
+               size = File.size( src_file )
+               checksum = Utils.checksum( src_file )
+
+               if is_client then
+                       conn.puts "RECEIVE_REQ"
+               end
+
+               while line = conn.gets()
+                       tok = line.split(",") { |x| x.strip }
+                       cmd = tok[0].strip
+                       case cmd
+                       when "SEND_REQ"
+                               conn.puts "FILE_INFO,#{filename},#{size},#{checksum}"
+                               # read file contents
+                               # send via tcp/ip
+                               File.open(src_file, "rb") do |io|
+                                       while size > 0
+                                               buf = io.read(size > 1024*1024 ? 1024*1024 : size)
+                                               conn.write( buf )
+                                               size -= buf.length
+                                       end
+                               end
+
+                               @log.info "Upload is succeeded!"
+                               conn.puts "SEND_OK"
+
+                               # wait for download result
+                       when "RECEIVE_OK"
+                               @log.info "Received download success message from remote site"
+                               return true
+
+                       when "RECEIVE_FAIL"
+                               @log.info "Received download fail message from remote site"
+                               return false
+
+                       else
+                               @log.error "Unhandled message: #{line}"
+                               return false
+                       end
+               end
+       end
+
+
+       def receive_file( dst_file, conn, is_client=false )
+
+               if is_client then
+                       conn.puts "SEND_REQ"
+               end
+
+               while line = conn.gets()
+                       tok = line.split(",") { |x| x.strip }
+                       cmd = tok[0].strip
+                       case cmd
+                       when "RECEIVE_REQ"
+                               conn.puts "SEND_REQ"
+                       when "FILE_INFO"
+                               @log.info "Received file info from remote site"
+                               filename = tok[1].strip
+                               size = tok[2].strip.to_i
+                               checksum = tok[3].strip
+
+                               if File.directory? dst_file then
+                                       dst_file = File.join(dst_file, filename)
+                               end
+
+                               File.open( dst_file, "wb" ) do  |io|
+                                       while size > 0
+                                               buf = conn.read(size > 1024*1024 ? 1024*1024 : size)
+                                               if buf.nil? then
+                                                       @log.error "Reading data from connection failed!"
+                                                       return false
+                                               end
+                                               io.write( buf )
+                                               size -= buf.length
+                                       end
+                               end
+
+                               conn.puts "RECEIVE_OK"
+
+                       when "SEND_OK"
+                               @log.info "Received success message from remote site"
+                               return true
+
+                       else
+                               @log.error "Unhandled message: #{line}"
+                               return false
+                       end
+               end
+       end
+end
diff --git a/src/common/FileTransferViaFTP.rb b/src/common/FileTransferViaFTP.rb
new file mode 100644 (file)
index 0000000..71a14d0
--- /dev/null
@@ -0,0 +1,288 @@
+=begin
+
+ FileTransferViaFTP.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 'socket'
+require 'log'
+
+class FileTransferFTP
+       attr_accessor :type
+       ATTEMPTS = ["first", "second", "third"]
+
+       def initialize(logger, ip=nil, port=nil, username=nil, passwd=nil )
+               @type = "FTP"
+               @ip = ip
+               @port = port
+               @username = username
+               @passwd = passwd
+               if not logger.nil? then
+                       @log = logger
+               else
+                       @log = DummyLog.new
+               end
+       end
+
+
+       def send_file( src_file, conn, is_client=true )
+
+               if is_client then
+                       # check ftp info
+                       if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+                               @log.error "No FTP information!"
+                               conn.puts "UPLOAD_FAIL"
+                               return false
+                       end
+                       conn.puts "DOWNLOAD_REQ,#{@ip},#{@port},#{@username},#{@passwd}"
+               end
+
+               ip = @ip; port = @port; username = @username; passwd = @passwd
+               while line = conn.gets()
+                       tok = line.split(",") { |x| x.strip }
+                       cmd = tok[0].strip
+                       case cmd
+                       when "UPLOAD_REQ"
+                               if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+                                       ip = tok[1].strip
+                                       port = tok[2].strip
+                                       username = tok[3].strip
+                                       passwd = tok[4].strip
+                                       @log.info "Using FTP information from remote... [#{ip}, #{port}]"
+                               end
+
+                               # upload to ftp
+                               ftp_filepath = nil
+                               for attempt in ATTEMPTS
+                                       ftp_filepath = putfile( src_file, ip, port, username, passwd )
+                                       if !ftp_filepath.nil? then
+                                               break
+                                       else
+                                               @log.info "The #{attempt} uploading attempt failed!"
+                                       end
+                               end
+
+                               if ftp_filepath.nil? then
+                                       conn.puts "UPLOAD_FAIL"
+                                       return false
+                               else
+                                       @log.info "Upload is succeeded at #{attempt}"
+                                       conn.puts "UPLOAD_OK,#{ftp_filepath}"
+                               end
+
+                               # wait for download result
+                       when "DOWNLOAD_OK"
+                               @log.info "Received download success message from remote site"
+                               # clean
+                               cleandir( ftp_filepath, ip, port, username, passwd)
+                               @log.info "Cleaned temporary dir on FTP server: #{ftp_filepath}"
+                               return true
+
+                       when "DOWNLOAD_FAIL"
+                               @log.info "Received download fail message from remote site"
+                               return false
+
+                       else
+                               @log.error "Unhandled message: #{line}"
+                               return false
+                       end
+               end
+       end
+
+
+       def receive_file( dst_file, conn, is_client=false )
+
+               if is_client then
+                       # check ftp info
+                       if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+                               @log.error "No FTP information!"
+                               conn.puts "DOWNLOAD_FAIL"
+                               return false
+                       end
+                       conn.puts "UPLOAD_REQ,#{@ip},#{@port},#{@username},#{@passwd}"
+               end
+
+               ip = @ip; port = @port; username = @username; passwd = @passwd
+               while line = conn.gets()
+                       tok = line.split(",") { |x| x.strip }
+                       cmd = tok[0].strip
+                       case cmd
+                       when "DOWNLOAD_REQ"
+                               if @ip.nil? or @port.nil? or @username.nil? or @passwd.nil? then
+                                       ip = tok[1].strip
+                                       port = tok[2].strip
+                                       username = tok[3].strip
+                                       passwd = tok[4].strip
+                                       @log.info "Using FTP information from remote... [#{ip}, #{port}]"
+                               end
+
+                               conn.puts "UPLOAD_REQ,#{ip},#{port},#{username},#{passwd}"
+                       when "UPLOAD_OK"
+                               @log.info "Received upload success message from remote site"
+                               filepath = tok[1].strip
+                               # download from ftp
+                               dst_filepath = nil
+                               for attempt in ATTEMPTS
+                                       dst_filepath = getfile( filepath, dst_file, ip, port, username, passwd )
+                                       if not dst_filepath.nil? then
+                                               break
+                                       else
+                                               @log.info "The #{attempt} downloading attempt failed!"
+                                       end
+                               end
+                               if dst_filepath.nil? then
+                                       conn.puts "DOWNLOAD_FAIL"
+                                       return false
+                               else
+                                       @log.info " Server is the #{attempt} successful attempt to download"
+                                       conn.puts "DOWNLOAD_OK"
+                                       return true
+                               end
+
+                       when "UPLOAD_FAIL"
+                               @log.info "Received upload fail message from remote site"
+                               return false
+
+                       else
+                               @log.error "Unhandled message: #{line}"
+                               return false
+                       end
+               end
+       end
+
+
+       def putfile( bpath, ip, port, username, passwd )
+               filename = File.basename(bpath)
+               uniqdir = Utils.create_uniq_name
+               ftp_filepath = File.join(uniqdir, filename)
+
+               begin
+                       ftp = Net::FTP.new
+                       if port.nil? or port == "" then
+                               ftp.connect(ip)
+                       else
+                               ftp.connect(ip, port)
+                       end
+                       @log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+                       ftp.login(username, passwd)
+                       ftp.binary = true
+                       ftp.passive = true
+                       ftp.mkdir(uniqdir)
+                       ftp.chdir(uniqdir)
+                       ftp.put(bpath)
+                       @log.info "[FTP log] Put a file"
+                       @log.info "[FTP log]   from \"#{bpath}\" to \"#{ftp_filepath}\""
+                       files = ftp.list(filename)
+                       if files.empty? then
+                               @log.error "[FTP log] Failed to upload file (#{filename} does not exist)"
+                               return nil
+                       end
+                       ftp.quit
+                       @log.info "[FTP log] Disconnected FTP server"
+               rescue => e
+                       @log.error "[FTP log] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return nil
+               end
+               return ftp_filepath
+       end
+
+       def getfile( bpath, target, ip, port, username, passwd )
+               dirname = File.dirname(bpath)
+               filename = File.basename(bpath)
+
+               # target can be directory or file
+               if File.directory? target then
+                       dst_file = File.join(target,filename)
+               else
+                       dst_file = target
+               end
+
+               begin
+                       ftp = Net::FTP.new
+                       if port.nil? or port == "" then
+                               ftp.connect(ip)
+                       else
+                               ftp.connect(ip, port)
+                       end
+                       @log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+                       ftp.login(username, passwd)
+                       ftp.binary = true
+                       ftp.passive = true
+                       ftp.chdir(dirname)
+                       ftp.get(filename, dst_file)
+                       @log.info "[FTP log] Get a file"
+                       @log.info "[FTP log]   from \"#{bpath}\" to \"#{dst_file}\""
+                       ftp.quit
+                       @log.info "[FTP log] Disconnected FTP server"
+               rescue => e
+                       @log.error "[FTP log] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return nil
+               end
+               if not File.exist? dst_file then
+                       @log.error "[FTP log] Failed to download file (#{dst_file} does not exist)"
+                       return nil
+               end
+               return bpath
+       end
+
+       def cleandir(path, ip, port, username, passwd)
+               dirname = File.dirname(path)
+
+               begin
+                       ftp = Net::FTP.new
+                       if port.nil? or port == "" then
+                               ftp.connect(ip)
+                       else
+                               ftp.connect(ip, port)
+                       end
+                       @log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+                       ftp.login(username, passwd)
+                       old_dir = ftp.pwd
+                       ftp.chdir(dirname)
+                       list = ftp.ls
+                       # TODO: if list is directory?
+                       list.each do |l|
+                               file = l.split(" ")[-1].strip
+                               ftp.delete(file)
+                       end
+                       ftp.chdir(old_dir)
+                       ftp.rmdir(dirname)
+                       @log.info "[FTP log] Clean dir (#{dirname})"
+                       ftp.quit
+                       @log.info "[FTP log] Disconnected FTP server"
+               rescue => e
+                       @log.error "[FTP log] Exception"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return nil
+               end
+
+               return true
+       end
+end
index 4a9c2d3f6aa0a4316d41003d3d3342725e3b15b8..c946dd2ab00c422cb7e6779cd7addd313b408138 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  PackageManifest.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -33,45 +33,38 @@ class PackageManifest
        attr_accessor :packages
 
        def initialize( file_path )
-               @pkg_map = Parser.read_pkginfo_list( file_path )
-               @packages = @pkg_map.values
+               @packages = Parser.read_multy_pkginfo_from file_path
        end
 
 
        # scan all build dependencies
-       def get_build_dependencies( target_os, host_os )
+       def get_build_dependencies( target_os )
                # for all
                list = []
-               for pkg in @packages
+               @packages.each do |pkg|
                        # package that has the target os
-                       if not pkg.os.include?(target_os)
+                       if not pkg.os_list.include?(target_os)
                                next
                        end
 
-                       # package that has the host os
-                       if not pkg.build_host_os.include?(host_os)
-                               next
-                       end
                        # package that has the target os
-                       for dep in pkg.build_dep_list
-                       #       if dep.target_os_list.include? target_os
-                                       list.push dep
-                       #       end
+                       pkg.build_dep_list.each do |dep|
+                               list.push dep
                        end
                end
                list.uniq!
-               
+
                return list
-       end     
+       end
 
-       
-       # scan all build dependencies
+
+       # scan all source dependencies
        def get_source_dependencies( target_os, host_os )
                # for all
                list = []
-               for pkg in @packages
+               @packages.each do |pkg|
                        # only package that used in target os
-                       if not pkg.os.include?(target_os)
+                       if not pkg.os_list.include?(target_os)
                                next
                        end
 
@@ -81,27 +74,79 @@ class PackageManifest
                        end
 
                        # package that has the target os
-                       for dep in pkg.source_dep_list
-                       #       if dep.target_os_list.include? target_os
-                                       list.push dep
-                       #       end
+                       pkg.source_dep_list.each do |dep|
+                               #       if dep.target_os_list.include? target_os
+                               list.push dep
+                               #       end
+                       end
+               end
+               list.uniq!
+
+               return list
+       end
+
+
+       # scan all install dependencies
+       def get_install_dependencies( target_os, pkg_name=nil )
+               # for all
+               list = []
+               @packages.each do |pkg|
+                       if not pkg_name.nil? and pkg.package_name != pkg_name then next end
+                       # only package that used in target os
+                       if not pkg.os_list.include?(target_os)
+                               next
+                       end
+
+                       # package that has the target os
+                       pkg.install_dep_list.each do |dep|
+                               list.push dep
                        end
                end
                list.uniq!
 
                return list
-       end     
+       end
 
 
        def package_exist?(target_os, host_os)
-               for pkg in @packages
+               @packages.each do |pkg|
                        # only package that used in target os
-                       if pkg.os.include?(target_os) and 
+                       if pkg.os_list.include?(target_os) and
                                pkg.build_host_os.include?(host_os)
                                return true
                        end
                end
 
                return false
-       end     
+       end
+
+
+       def get_version()
+               return @packages[0].version
+       end
+
+
+       def get_target_packages(target_os)
+               pkgs = []
+               @packages.each do |pkg|
+                       if pkg.os_list.include?(target_os) then
+                               pkgs.push pkg
+                       end
+               end
+
+               return pkgs
+       end
+
+
+       def pkg_exist?(name,ver,os)
+               @packages.each do |pkg|
+                       if pkg.package_name != name then next end
+                       if not ver.nil? and pkg.version != ver then next end
+                       if not os.nil? and not pkg.os_list.include?(os) then next end
+
+                       return true
+               end
+
+               return false
+       end
 end
diff --git a/src/common/ScheduledActionHandler.rb b/src/common/ScheduledActionHandler.rb
new file mode 100644 (file)
index 0000000..edbd691
--- /dev/null
@@ -0,0 +1,117 @@
+=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__)
+require 'thread'
+
+class ScheduledActionHandler
+       attr_accessor :quit, :thread
+
+       # init
+       def initialize( )
+               @thread = nil
+               @quit = false
+               @actions = []
+               @mutex = Mutex.new
+       end
+
+
+       # register a action
+       def register( action )
+               # init action
+               action.init
+               # add to list
+               @mutex.synchronize do
+                       @actions.push action
+               end
+       end
+
+
+       # unregsister a action
+       def unregister( action )
+               @mutex.synchronize do
+                       @actions.delete(action)
+               end
+       end
+
+
+       # get all actions
+       def get_actions()
+               return @actions
+       end
+
+
+       # start thread
+       def start()
+               @thread = Thread.new do
+                       # main
+                       thread_main()
+
+                       # close
+                       terminate()
+               end
+       end
+
+
+       protected
+
+       def thread_main
+
+               while not @quit
+
+                       current_time = Time.new
+
+                       # get list
+                       action_list = Array.new(@actions)
+                       action_list.each do |action|
+                               # if its time is reached, execute action
+                               if not action.time.nil? and current_time > action.time then
+                                       action.execute
+
+                                       # if periodic action, renew the time
+                                       # else remove it from list
+                                       if action.period != 0   then
+                                               while current_time > action.time
+                                                       action.time = action.time  + action.period
+                                               end
+                                       else
+                                               unregister(action)
+                                       end
+                               end
+                       end
+
+                       # sleep 10 sec
+                       sleep 10
+               end
+       end
+
+
+       def terminate
+       end
+
+end
index 3bdba12f97cf8d6d2c8eb394ecd3ee7e3fcad8cb..7d7921d59e38241cb394853057974ecd0eeee820 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  Version.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -28,22 +28,11 @@ Contributors:
 
 
 class Version < Array
-       def initialize s
-       super(s.split('.').map { |e| e.to_i })   
-       end   
-       def < x     
-               (self <=> x) < 0   
-       end   
-       def <= x     
-               (self <=> x) <= 0   
-       end   
-       def > x     
-               (self <=> x) > 0   
-       end   
-       def >= x     
-               (self <=> x) >= 0   
-       end   
-       def == x     
-               (self <=> x) == 0   
-       end 
-end 
+       include Comparable
+       def initialize s
+               super(s.split('.').map { |e| e.to_i })
+       end
+       def compare x
+               self <=> x
+       end
+end
index a6e9499f13fa9e969ee66432a059de688f77382f..74b5ae621ada2bda55676a68ab3c04c0a84057d9 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
   dependency.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -27,31 +27,31 @@ Contributors:
 =end
 
 $LOAD_PATH.unshift File.dirname(__FILE__)
-require "Version" 
+require "Version"
 
 class Dependency
-    attr_accessor :package_name, :comp, :base_version, :target_os_list
-    def initialize (package_name, comp, base_version, target_os_list)
-        @package_name = package_name
-        @comp = comp
-        @base_version = base_version
-        @target_os_list = target_os_list
-    end 
+       attr_accessor :package_name, :comp, :base_version, :target_os_list
+       def initialize (package_name, comp, base_version, target_os_list)
+               @package_name = package_name
+               @comp = comp
+               @base_version = base_version
+               @target_os_list = target_os_list
+       end
 
-    def to_s
-        string = @package_name 
-        if not @comp.nil? and not @base_version.nil? then 
-            string = string + " ( #{@comp} #{@base_version} )" 
-        end
-        if not @target_os_list.empty? then 
-            string = string + " [ #{@target_os_list.join("|")} ]"
-        end 
-        return string
-    end 
+       def to_s
+               string = @package_name
+               if not @comp.nil? and not @base_version.nil? then
+                       string = string + " ( #{@comp} #{@base_version} )"
+               end
+
+               if not @target_os_list.empty? then
+                       string = string + " [ #{@target_os_list.join("|")} ]"
+               end
+               return string
+       end
 
        def match? ver
-               if @base_version.nil? 
+               if @base_version.nil?
                        return true
                end
 
@@ -68,7 +68,7 @@ class Dependency
                        return Version.new(ver) < Version.new(@base_version)
                else
                        return true
-               end     
+               end
        end
-end 
+end
 
diff --git a/src/common/execute_with_log.rb b/src/common/execute_with_log.rb
new file mode 100755 (executable)
index 0000000..58cb982
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/ruby
+=begin
+
+ execute_with_log.rb
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <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 'logger'
+$LOAD_PATH.unshift File.dirname(__FILE__)
+require 'utils.rb'
+
+# parse arguments
+cmd = ARGV[0]
+log_path = ARGV[1]
+
+# create logger
+if log_path.nil? or log_path.empty? then
+       log = DummyLog.new
+else
+       log = Logger.new(log_path)
+end
+
+# generate command
+cmd = Utils.generate_shell_command(cmd, nil)
+
+# execute and write log
+IO.popen("#{cmd} 2>&1") do  |io|
+       io.each do  |line|
+               log.info line
+       end
+end
+
+# return exit code
+exit $?.exitstatus
index afa8fd794d52e232cb016cb280cfc971c032f46f..893885fb3015f9fd9b9fd24ca8af65bfc92c5d21 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  log.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -30,7 +30,7 @@ require "logger"
 
 class Log
 
-       attr_accessor :path
+       attr_accessor :path, :cnt
 
        # Log LEVEL
        LV_NORMAL = 1
@@ -39,7 +39,8 @@ class Log
 
        # init
        def initialize(path, lv=LV_USER)
-        @path = path
+               @cnt = 0
+               @path = path
                if @path.nil? then
                        @logger = Logger.new(STDOUT)
                else
@@ -52,43 +53,47 @@ class Log
                # diable logger format
                @default_formatter = @logger.formatter
                @no_prefix_formatter = proc do |severity, datetime, progname, msg|
-                       " >#{msg}"                      
+                       " >#{msg}"
                end
        end
 
 
        def info(msg, lv=LV_NORMAL)
-        if @path.nil? then puts "Info: #{msg}"
-        else @logger.info msg end
-               if not @second_out.nil? and lv >= @second_out_level then 
-                       output_extra "Info: " + msg 
+               if @path.nil? and not @second_out.nil? then puts "Info: #{msg}"
+               else @logger.info msg end
+               if not @second_out.nil? and lv >= @second_out_level then
+                       output_extra "Info: " + msg
                end
-       end     
+               @cnt = @cnt + 1
+       end
 
-       def warn(msg, lv=LV_NORMAL) 
-        if @path.nil? then puts "Warn: #{msg}"
+       def warn(msg, lv=LV_NORMAL)
+               if @path.nil? and not @second_out.nil? then puts "Warn: #{msg}"
                else @logger.warn msg end
                if not @second_out.nil? and lv >= @second_out_level then
-                       output_extra "Warn: " + msg 
+                       output_extra "Warn: " + msg
                end
-       end     
+               @cnt = @cnt + 1
+       end
 
 
-       def error(msg, lv=LV_NORMAL) 
-        if @path.nil? then puts "Error: #{msg}"
+       def error(msg, lv=LV_NORMAL)
+               if @path.nil? and not @second_out.nil? then puts "Error: #{msg}"
                else @logger.error msg end
                if not @second_out.nil? and lv >= @second_out_level then
-                       output_extra "Error: " + msg 
+                       output_extra "Error: " + msg
                end
+               @cnt = @cnt + 1
        end
 
 
-       def output(msg, lv=LV_NORMAL) 
-        if @path.nil? then puts msg
+       def output(msg, lv=LV_NORMAL)
+               if @path.nil? and not @second_out.nil? then puts msg
                else @logger.info msg end
                if not @second_out.nil? and lv >= @second_out_level then
-                       output_extra msg 
+                       output_extra msg
                end
+               @cnt = @cnt + 1
        end
 
 
@@ -96,10 +101,47 @@ class Log
                @second_out= nil
        end
 
+       def is_verbose
+               return @second_out_level.eql? Log::LV_NORMAL
+       end
+
 
        protected
        def output_extra(msg)
-               #do nothing     
-       end     
+               #do nothing
+       end
+end
 
+
+class DummyLog
+       attr_accessor :path, :cnt
+       def initialize()
+               @path = ""
+               @cnt = 0
+       end
+       def info(str, lv=nil)
+               puts "I, [#{Time.now.strftime("%Y-%m-%dT%H:%M:%S")}] INFO -- : " + str
+       end
+       def error(str, lv=nil)
+               puts "E, [#{Time.now.strftime("%Y-%m-%dT%H:%M:%S")}] ERROR -- : " + str
+       end
+       def warn(str, lv=nil)
+               puts "W, [#{Time.now.strftime("%Y-%m-%dT%H:%M:%S")}] WARN -- : " + str
+       end
+       def output(str, lv=nil)
+               puts "" + str
+       end
+end
+
+class StandardOutLog < Log
+
+       def initialize(path)
+               super(path)
+               @second_out = $stdout
+       end
+
+       protected
+       def output_extra(msg)
+               @second_out.puts msg
+       end
 end
index a49c1d22a34a48c72c27a3ebab09670fe24a1d52..aedc753327341a28b553bfaea53aac06bfc476a2 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  mail.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -30,15 +30,15 @@ require 'net/smtp'
 $LOAD_PATH.unshift File.dirname(__FILE__)
 require "mailConfig"
 
-class Mail 
+class Mail
 
-       def Mail.send_mail( mail_to, subject, contents ) 
+       def Mail.send_mail( mail_to, subject, contents )
 
                if mail_to.nil? or mail_to.empty? \
-                               or subject.nil? or subject.empty? \
-                               or contents.nil? or contents.empty? then 
+                       or subject.nil? or subject.empty? \
+                       or contents.nil? or contents.empty? then
                        return false
-               end 
+               end
 
                message = <<MESSAGE_END
 From: #{SENDER}
@@ -48,19 +48,19 @@ Subject: #{subject}
 #{contents}
 
 MESSAGE_END
-               
-               Mail.send_mail2( mail_to, message )
+
+Mail.send_mail2( mail_to, message )
        end
 
        def Mail.send_mail2( mail_to_list, message )
-               if mail_to_list.empty? then 
+               if mail_to_list.empty? then
                        puts "There is no maintainer email address "
                else
-                       begin 
-                       Net::SMTP.start('localhost') do |smtp|
-                       smtp.send_message( message, SENDER, mail_to_list) 
-                               end 
-                       rescue => e 
+                       begin
+                               Net::SMTP.start('localhost') do |smtp|
+                                       smtp.send_message( message, SENDER, mail_to_list)
+                               end
+                       rescue => e
                                puts "Can't send result email"
                                puts e.message
                        end
@@ -69,18 +69,18 @@ MESSAGE_END
 
        def Mail.parse_email( low_email_list )
                mail_list = []
-               low_email_list.each do | low_email |  
+               low_email_list.split(",").each do | low_email |
                        ms = low_email.index('<')
-                       me = low_email.index('>')
-                       if ms.nil? or me.nil? then  
-                               next 
-                       else 
-                               mail = low_email[(ms+1)..(me-1)] 
-                       end
-                       
-                       if mail.include?("@") then mail_list.push mail end
-               end 
+               me = low_email.index('>')
+               if ms.nil? or me.nil? then
+                       next
+               else
+                       mail = low_email[(ms+1)..(me-1)]
+               end
+
+               if mail.include?("@") then mail_list.push mail end
+               end
 
-               return mail_list 
+               return mail_list
        end
 end
index 122f97709088c6ef4e312b00ffe707b5b8f7528a..a7c139f6f22d4f867ee34134b6ded1bac27a266b 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- package.rb 
+
+ package.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -27,135 +27,88 @@ Contributors:
 =end
 
 class Package
-    attr_accessor :package_name, :version, :os, :build_host_os, :maintainer, :attribute, :install_dep_list, :build_dep_list, :source_dep_list, :conflicts, :source, :src_path, :path, :origin, :checksum, :size, :description
-    def initialize (package_name)
-        @package_name = package_name
-        @version = ""
-        @os = ""
-        @build_host_os = []
-        @maintainer = ""
-        @attribute = []
-        @install_dep_list = []
-        @build_dep_list = []
-        @source_dep_list = []
-        @conflicts = []
-        @source = ""
-        @src_path = ""
-        @path = ""
-        @origin = ""
-        @checksum = ""
-        @size = ""
-        @description = ""
-    end 
-    def print
-        puts "Package : " + @package_name
-        if not @version.empty? then puts "Version : " + @version end 
-        if not @os.empty? then puts "OS : " + @os end 
-        if not @build_host_os.empty? then puts "Build-host-os : " + @build_host_os.join("|") end 
-        if not @maintainer.empty? then puts "Maintainer : " + @maintainer end 
-        if not @attribute.empty? then puts "Attribute : " + @attribute.join("|") end 
-        if not @install_dep_list.empty? then 
-            puts "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @build_dep_list.empty? then 
-            puts "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source_dep_list.empty? then 
-            puts "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @conflicts.empty? then 
-            puts "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source.empty? then puts "Source : " + @source end 
-        if not @src_path.empty? then puts "Src-path : " + @src_path end 
-        if not @path.empty? then puts "Path : " + @path end 
-        if not @origin.empty? then puts "Origin : " + @origin end 
-        if not @checksum.empty? then puts "SHA256 : " + @checksum end 
-        if not @size.empty? then puts "Size : " + @size end 
-        if not @description.empty? then puts "Description : " + @description end 
-    end 
+       attr_accessor :package_name, :label, :version, :os, :build_host_os, :maintainer, :attribute, :install_dep_list, :build_dep_list, :source_dep_list, :conflicts, :source, :src_path, :path, :origin, :checksum, :size, :description, :os_list, :custom, :change_log
+       def initialize (package_name)
+               @package_name = package_name
+               @label = ""
+               @version = ""
+               @os = ""
+               @os_list = []
+               @build_host_os = []
+               @maintainer = ""
+               @attribute = []
+               @install_dep_list = []
+               @build_dep_list = []
+               @source_dep_list = []
+               @conflicts = []
+               @source = ""
+               @src_path = ""
+               @path = ""
+               @origin = ""
+               @checksum = ""
+               @size = ""
+               @description = ""
+               @custom = ""
+               @change_log = {}
+       end
+
+       def print
+               puts self.to_s
+       end
+
+       def to_s
+               string =  "Package : " + @package_name
+               if not @label.empty? then string = string + "\n" +  "Label : " + @label end
+               if not @version.empty? then string = string + "\n" +  "Version : " + @version end
+               if not @os_list.empty? then string = string + "\n" + "OS : " + @os_list.join(", ") end
+               if not @build_host_os.empty? then string = string + "\n" + "Build-host-os : " + @build_host_os.join(", ") end
+               if not @maintainer.empty? then string = string + "\n" + "Maintainer : " + @maintainer end
+               if not @attribute.empty? then string = string + "\n" + "Attribute : " + @attribute.join("|") end
+               if not @install_dep_list.empty? then
+                       string = string + "\n" + "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ")
+               end
+               if not @build_dep_list.empty? then
+                       string = string + "\n" + "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
+               end
+               if not @source_dep_list.empty? then
+                       string = string + "\n" + "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
+               end
+               if not @conflicts.empty? then
+                       string = string + "\n" + "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ")
+               end
+               if not @source.empty? then string = string + "\n" + "Source : " + @source end
+               if not @src_path.empty? then string = string + "\n" + "Src-path : " + @src_path end
+               if not @path.empty? then string = string + "\n" + "Path : " + @path end
+               if not @origin.empty? then string = string + "\n" + "Origin : " + @origin end
+               if not @checksum.empty? then string = string + "\n" + "SHA256 : " + @checksum end
+               if not @size.empty? then string = string + "\n" + "Size : " + @size end
+               if not @custom.empty? then string = string + "\n" + @custom end
+               if not @description.empty? then string = string + "\n" + "Description : " + @description end
+               return string
+       end
+
+       def print_to_file(file)
+               file.puts self.to_s
+       end
+
+       def change_log_string
+               if @change_log.empty? then return "" end
+
+               string = ""
+               @change_log.sort.each do |list|
+                       string = "* " + list[0] + "\n" + list[1] + "\n" + string
+               end
+               return "#Change log\n" + string
+       end
 
-    def to_s
-        string =  "Package : " + @package_name
-        if not @version.empty? then string = string + "\n" +  "Version : " + @version end 
-        if not @os.empty? then string = string + "\n" + "OS : " + @os end 
-        if not @build_host_os.empty? then string = string + "\n" + "Build-host-os : " + @build_host_os.join("|") end 
-        if not @maintainer.empty? then string = string + "\n" + "Maintainer : " + @maintainer end 
-        if not @attribute.empty? then string = string + "\n" + "Attribute : " + @attribute.join("|") end 
-        if not @install_dep_list.empty? then 
-            string = string + "\n" + "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @build_dep_list.empty? then 
-            string = string + "\n" + "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source_dep_list.empty? then 
-            string = string + "\n" + "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @conflicts.empty? then 
-            string = string + "\n" + "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source.empty? then string = string + "\n" + "Source : " + @source end 
-        if not @src_path.empty? then string = string + "\n" + "Src-path : " + @src_path end 
-        if not @path.empty? then string = string + "\n" + "Path : " + @path end 
-        if not @origin.empty? then string = string + "\n" + "Origin : " + @origin end 
-        if not @checksum.empty? then string = string + "\n" + "SHA256 : " + @checksum end 
-        if not @size.empty? then string = string + "\n" + "Size : " + @size end 
-        if not @description.empty? then string = string + "\n" + "Description : " + @description end 
-        return string 
-    end 
-    def print_to_file(file)
-        file.puts "Package : " + @package_name
-        if not @version.empty? then file.puts "Version : " + @version end 
-        if not @os.empty? then file.puts "OS : " + @os end 
-        if not @build_host_os.empty? then file.puts "Build-host-os : " + @build_host_os.join("|") end 
-        if not @maintainer.empty? then file.puts "Maintainer : " + @maintainer end 
-        if not @attribute.empty? then file.puts "Attribute : " + @attribute.join("|") end 
-        if not @install_dep_list.empty? then 
-            file.puts "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @build_dep_list.empty? then 
-            file.puts "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source_dep_list.empty? then 
-            file.puts "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @conflicts.empty? then 
-            file.puts "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source.empty? then file.puts "Source : " + @source end 
-        if not @src_path.empty? then file.puts "Src-path : " + @src_path end 
-        if not @path.empty? then file.puts "Path : " + @path end 
-        if not @origin.empty? then file.puts "Origin : " + @origin end 
-        if not @checksum.empty? then file.puts "SHA256 : " + @checksum end 
-        if not @size.empty? then file.puts "Size : " + @size end 
-        if not @description.empty? then file.puts "Description : " + @description end 
-    end
+       def does_change_exist?
+               if not @change_log.empty? and not @change_log[@version].nil? then
+                       return true
+               end
+               return false
+       end
 
-    def print_to_file_with_os(file,target_os)
-        file.puts "Package : " + @package_name
-        if not @version.empty? then file.puts "Version : " + @version end 
-        file.puts "OS : " + target_os
-        if not @build_host_os.empty? then file.puts "Build-host-os : " + @build_host_os.join("|") end 
-        if not @maintainer.empty? then file.puts "Maintainer : " + @maintainer end 
-        if not @attribute.empty? then file.puts "Attribute : " + @attribute.join("|") end 
-        if not @install_dep_list.empty? then 
-            file.puts "Install-dependency : " + @install_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @build_dep_list.empty? then 
-            file.puts "Build-dependency : " + @build_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source_dep_list.empty? then 
-            file.puts "Source-dependency : " + @source_dep_list.map {|x| x.to_s}.join(", ")
-        end 
-        if not @conflicts.empty? then 
-            file.puts "Conflicts : " + @conflicts.map {|x| x.to_s}.join(", ")
-        end 
-        if not @source.empty? then file.puts "Source : " + @source end 
-        if not @src_path.empty? then file.puts "Src-path : " + @src_path end 
-        if not @path.empty? then file.puts "Path : " + @path end 
-        if not @origin.empty? then file.puts "Origin : " + @origin end 
-        if not @checksum.empty? then file.puts "SHA256 : " + @checksum end 
-        if not @size.empty? then file.puts "Size : " + @size end 
-        if not @description.empty? then file.puts "Description : " + @description end 
-    end
-end 
+       def get_changes
+               return @change_log[@version]
+       end
+end
index 01f7acf6c36aa1bcac3849b6f015933797efc5e1..87949e0b54ebb7128c4c126fcf3b65e5bb3ffd4b 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- parser.rb 
+
+ parser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -31,209 +31,290 @@ require "package"
 require "dependency"
 
 class Parser
-    def Parser.read_pkginfo_list (file)
-        pkglist = {}
-        File.open file,"r" do |f|
-            #variable initialize
-            package_name = ""
-            version = ""
-            os = ""
-            build_host_os = []
-            maintainer = ""
-            attribute = []
-            install_dep_list = [] 
-            build_dep_list = []
-            source_dep_list = []
-            conflicts = []
-            source = ""
-            src_path = ""
-            path = ""
-            origin = ""
-            checksum = ""
-            size = ""
-            description = ""
-
-            f.each_line do |l|
-                # separator
-                if l.strip.empty? then 
-                    #make package and initialize
-                    if not package_name.empty? and not os.empty? then 
-                        package = Package.new(package_name)
-                        if not version.empty? then package.version = version end 
-                        if not os.empty? then package.os = os end 
-                        if not build_host_os.empty? then package.build_host_os = build_host_os end 
-                        if not maintainer.empty? then package.maintainer = maintainer end 
-                        if not attribute.empty? then package.attribute = attribute end 
-                        if not install_dep_list.empty? then package.install_dep_list = install_dep_list end 
-                        if not build_dep_list.empty? then package.build_dep_list = build_dep_list end 
-                        if not source_dep_list.empty? then package.source_dep_list = source_dep_list end 
-                        if not conflicts.empty? then package.conflicts = conflicts end 
-                        if not source.empty? then package.source = source end 
-                        if not src_path.empty? then package.src_path = src_path end 
-                        if not path.empty? then package.path = path end 
-                        if not origin.empty? then package.origin = origin end 
-                        if not checksum.empty? then package.checksum = checksum end 
-                        if not size.empty? then package.size = size end 
-                        if not description.empty? then package.description = description end 
-                        pkglist[[package_name,os]] = package
-                        package_name = ""
-                        version = ""
-                        os = ""
-                        bulid_host_os = []
-                        maintainer = ""
-                        attribute = []
-                        install_dep_list = [] 
-                        build_dep_list = []
-                        source_dep_list = []
-                        conflicts = []
-                        source = ""
-                        src_path = ""
-                        path = ""
-                        origin = ""
-                        checksum = ""
-                        size = ""
-                        description = ""
-                    end 
-                    next
-                end 
-                # commant 
-                if l.strip.start_with? "#" then next end 
-                #contents
-                dsic_on = false
-                case l.strip.split(':')[0].strip
-                when /^Package/i then 
-                    package_name = l.sub(/^[ \t]*Package[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Version/i then 
-                    version = l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip 
-                    disc_on=false
-                when /^OS/i then 
-                    os = l.sub(/^[ \t]*OS[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Build-host-os/i then 
-                    build_host_os = l.sub(/^[ \t]*Build-host-os[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split("|")
-                    disc_on=false
-                when /^Maintainer/i then 
-                    maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Attribute/i then 
-                    attribute = l.sub(/^[ \t]*Attribute[ \t]*:[ \t]*/i,"").tr(" \t\n\r","").split("|")
-                    disc_on=false
-                when /^Install-dependency/i then 
-                    install_dep_list = dep_parser l.sub(/^[ \t]*Install-dependency[ \t]*:[ \t]*/i,"").split(',')
-                    disc_on=false
-                when /^Build-dependency/i then 
-                    build_dep_list = dep_parser l.sub(/^[ \t]*Build-dependency[ \t]*:[ \t]*/i,"").split(',')
-                    disc_on=false
-                when /^Source-dependency/i then 
-                    source_dep_list = dep_parser l.sub(/^[ \t]*Source-dependency[ \t]*:[ \t]*/i,"").split(',')
-                    disc_on=false
-                when /^Conflicts/i then 
-                    conflicts = dep_parser l.sub(/^[ \t]*Conflicts[ \t]*:[ \t]*/i,"").split(',')
-                    disc_on=false
-                when /^Source/i then 
-                    source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Src-path/i then 
-                    src_path = l.sub(/^[ \t]*Src-path[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Path/i then 
-                    path = l.sub(/^[ \t]*Path[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Origin/i then 
-                    origin = l.sub(/^[ \t]*Origin[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^SHA256/i then 
-                    checksum = l.sub(/^[ \t]*SHA256[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Size/i then 
-                    size = l.sub(/^[ \t]*Size[ \t]*:[ \t]*/i,"").strip
-                    disc_on=false
-                when /^Description/i then 
-                    description = l.sub(/^[ \t]*Description[ \t]*:[ \t]*/i,"")
-                    disc_on=true
-                else   
-                    if disc_on then 
-                        description = description + l
-                    else 
-                        puts "unknown section : #{l}"
-                    end
-                end 
-
-            end 
-            #i  essent
-
-            # check last package 
-            if not package_name.empty? and not os.empty? then 
-                package = Package.new(package_name)
-                if not version.empty? then package.version = version end 
-                if not os.empty? then package.os = os end 
-                if not build_host_os.empty? then package.build_host_os = build_host_os end 
-                if not maintainer.empty? then package.maintainer = maintainer end 
-                if not attribute.empty? then package.attribute = attribute end 
-                if not install_dep_list.empty? then package.install_dep_list = install_dep_list end 
-                if not build_dep_list.empty? then package.build_dep_list = build_dep_list end 
-                if not source_dep_list.empty? then package.source_dep_list = source_dep_list end 
-                if not conflicts.empty? then package.conflicts = conflicts end 
-                if not source.empty? then package.source = source end 
-                if not src_path.empty? then package.src_path = src_path end 
-                if not path.empty? then package.path = path end 
-                if not origin.empty? then package.origin = origin end 
-                if not checksum.empty? then package.checksum = checksum end 
-                if not size.empty? then package.size = size end 
-                if not description.empty? then package.description = description end 
-                pkglist[[package_name,os]] = package
-            end 
-        end 
-        return pkglist
-    end
-
-    def Parser.read_pkginfo (file)
-        return read_pkg_list(file).values[0]
-    end 
-
-    def Parser.read_pkg_list (file)
-        result = {}
-        read_pkginfo_list(file).values.each { |x| result[x.package_name]=x }
-        return result
-    end 
-
-    private
-    def Parser.dep_parser (string_list)
-        dependency_list = []
-        string_list.each do |dep|
-            #variable initialize
-            package_name = ""
-            comp = nil
-            base_version = nil
-            target_os_list = []
-            #string trim
-            dependency = dep.tr " \t\n", ""
-            #version extract
-            vs = dependency.index('(') 
-            ve = dependency.index(')') 
-            if not vs.nil? and not ve.nil? then 
-                comp = dependency[(vs+1)..(vs+2)]
-                base_version = dependency[(vs+3)..(ve-1)]
-            end 
-            #os list extract
-            os = dependency.index('[') 
-            oe = dependency.index(']') 
-            if not os.nil? and not oe.nil? then 
-                target_os_list = dependency[(os+1)..(oe-1)].split("|")
-            end 
-            # package_name extract
-            pe = dependency.index(/[\]\[\)\(]/)
-            if pe.nil?
-                package_name = dependency
-            else
-                package_name = dependency[0..pe-1]
-            end
-            #package_name check
-            if not package_name.empty? then 
-                dependency_list.push Dependency.new(package_name,comp,base_version,target_os_list)
-            end 
-        end 
-        return dependency_list
-    end 
-end 
+       def Parser.read_multy_pkginfo_from (file, only_common = false)
+               pkglist = []
+               package = nil
+               common_source = ""
+               common_version = ""
+               common_maintainer = ""
+               change_log = {}
+               multi_line = nil
+               change_version = nil
+               change_contents = ""
+
+               #file check
+
+               File.open file,"r" do |f|
+                       #variable initialize
+                       state = "INIT"
+                       f.each_line do |l|
+                               # commant
+                               if l.strip.start_with? "#" then next end
+
+                               field_name = l.split(':')[0].strip
+
+                               case state
+                               when "INIT" then
+                                       case field_name
+                                       when /^$/ then next
+                                       when /^Source$/i  then
+                                               state = "COMMON"
+                                               if common_source.empty? then common_source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                       when /^Version$/i then
+                                               state = "COMMON"
+                                               if common_version.empty? then common_version = check_version l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                       when /^Maintainer$/i then
+                                               state = "COMMON"
+                                               if common_maintainer.empty? then common_maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                       when /^Package$/i then
+                                               state = "PACKAGE"
+                                               package_name = l.sub(/^[ \t]*Package[ \t]*:[ \t]*/i,"").strip
+                                               if not package_name.empty? then
+                                                       package = Package.new(package_name)
+                                                       package.source = common_source
+                                                       package.version = common_version
+                                                       package.maintainer = common_maintainer
+                                               else
+                                                       raise RuntimeError, "Package name is not set in \"#{file}\" file"
+                                               end
+                                       when /^\*[ \t]*([0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*)[ \t]*$/ then
+                                               state = "CHANGELOG"
+                                               change_log[change_version] = change_contents.strip if not change_version.nil?
+                                               change_version = $1
+                                               change_contents = ""
+                                       when /^Include$/i then
+                                               pfile = File.dirname(file) + "/" + l.sub(/^[ \t]*Include[ \t]*:[ \t]*/i,"").strip
+                                               if File.exist? pfile then
+                                                       pkglist = pkglist + (Parser.read_multy_pkginfo_from pfile)
+                                                       list = Parser.read_multy_pkginfo_from(pfile, true)
+                                                       common_source = list[0] if common_source.empty?
+                                                       common_version = list[1] if common_version.empty?
+                                                       common_maintainer = list[2] if common_maintainer.empty?
+                                                       change_log = list[3] if change_log.empty?
+                                               else
+                                                       raise RuntimeError, "Not exist \"#{pfile}\""
+                                               end
+                                       when /^ORIGIN$/ then #for compatable
+                                               multi_line = nil
+                                               next
+                                       else raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}"
+                                       end
+                               when "COMMON" then
+                                       case field_name
+                                       when /^$/ then state = "INIT"
+                                       when /^Source$/i then
+                                               state = "COMMON"
+                                               if common_source.empty? then common_source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                       when /^Version$/i then
+                                               state = "COMMON"
+                                               if common_version.empty? then common_version = check_version l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                       when /^Maintainer$/i then
+                                               state = "COMMON"
+                                               if common_maintainer.empty? then common_maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                       when /^ORIGIN$/ then #for compatable
+                                               multi_line = nil
+                                               next
+                                       else raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}"
+                                       end
+                               when "PACKAGE" then
+                                       case field_name
+                                       when /^$/ then
+                                               state = "INIT"
+                                               if not package.package_name.empty? then
+                                                       pkglist.push package
+                                                       package = nil
+                                               else raise RuntimeError, "Package name is not set in \"#{file}\" file"
+                                               end
+                                               multi_line = nil
+                                       when /^Source$/i then
+                                               if common_source.empty? and package.source.empty? then package.source = l.sub(/^[ \t]*Source[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                               multi_line = nil
+                                       when /^Version$/i then
+                                               if common_version.empty? and package.version.empty? then package.version = check_version l.sub(/^[ \t]*Version[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                               multi_line = nil
+                                       when /^Maintainer$/i then
+                                               if common_maintainer.empty? and package.maintainer.empty? then package.maintainer = l.sub(/^[ \t]*Maintainer[ \t]*:[ \t]*/i,"").strip
+                                               else raise RuntimeError, "#{field_name} information is conflict in \"#{file}\" file\nIf use #{field_name} field in Common section then Package section can't contain #{field_name} field"
+                                               end
+                                               multi_line = nil
+                                       when /^OS$/i then
+                                               package.os_list = l.sub(/^[ \t]*OS[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split(",")
+                                               package.os = package.os_list[0]
+                                               multi_line = nil
+                                       when /^Label$/i then
+                                               package.label = l.sub(/^[ \t]*Label[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = nil
+                                       when /^Build-host-os$/i then
+                                               package.build_host_os = l.sub(/^[ \t]*Build-host-os[ \t]*:[ \t]*/i,"").tr(" \t\n\r", "").split(",")
+                                               multi_line = nil
+                                       when /^Attribute$/i then
+                                               package.attribute = l.sub(/^[ \t]*Attribute[ \t]*:[ \t]*/i,"").tr(" \t\n\r","").split("|")
+                                               multi_line = nil
+                                       when /^Install-dependency$/i then
+                                               package.install_dep_list = dep_parser l.sub(/^[ \t]*Install-dependency[ \t]*:[ \t]*/i,"").split(',')
+                                               multi_line = nil
+                                       when /^Build-dependency$/i then
+                                               package.build_dep_list = dep_parser l.sub(/^[ \t]*Build-dependency[ \t]*:[ \t]*/i,"").split(',')
+                                               multi_line = nil
+                                       when /^Source-dependency$/i then
+                                               package.source_dep_list = dep_parser l.sub(/^[ \t]*Source-dependency[ \t]*:[ \t]*/i,"").split(',')
+                                               multi_line = nil
+                                       when /^Conflicts$/i then
+                                               package.conflicts = dep_parser l.sub(/^[ \t]*Conflicts[ \t]*:[ \t]*/i,"").split(',')
+                                               multi_line = nil
+                                       when /^Src-path$/i then
+                                               package.src_path = l.sub(/^[ \t]*Src-path[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = nil
+                                       when /^Path$/i then
+                                               package.path = l.sub(/^[ \t]*Path[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = nil
+                                       when /^Origin$/i then
+                                               package.origin = l.sub(/^[ \t]*Origin[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = nil
+                                       when /^SHA256$/i then
+                                               package.checksum = l.sub(/^[ \t]*SHA256[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = nil
+                                       when /^Size$/i then
+                                               package.size = l.sub(/^[ \t]*Size[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = nil
+                                       when /^Description$/i then
+                                               package.description = l.sub(/^[ \t]*Description[ \t]*:[ \t]*/i,"").strip
+                                               multi_line = "Description"
+                                       when /^ORIGIN$/ then #for compatable
+                                               multi_line = nil
+                                               next
+                                       when /^C-/ then
+                                               if package.custom.empty? then package.custom = l.rstrip
+                                               else package.custom = package.custom + "\n" + l.rstrip
+                                               end
+                                               multi_line = nil
+                                       else
+                                               if multi_line.nil? then raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}" end
+                                               case multi_line
+                                               when "Description" then package.description = package.description + "\n" + l.rstrip
+                                               else raise RuntimeError, "Can't parse below line in \"#{file}\" file \n\t#{l}"
+                                               end
+                                       end
+                               when "CHANGELOG" then
+                                       case field_name
+                                       when /^$/ then
+                                               state = "INIT"
+                                               if not change_version.nil? then
+                                                       if change_log[change_version].nil? then change_log[change_version] = change_contents.strip
+                                                       else raise RuntimeError, "change log version is duplicated in \"#{file}\" file \n\t#{l}"
+                                                       end
+                                               end
+                                               change_version = nil
+                                               change_contents = ""
+                                       when /^\*[ \t]*([0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*)[ \t]*$/ then
+                                               if not change_version.nil? then
+                                                       if change_log[change_version].nil? then change_log[change_version] = change_contents.strip
+                                                       else raise RuntimeError, "change log version is duplicated in \"#{file}\" file \n\t#{l}"
+                                                       end
+                                               end
+                                               change_version = $1
+                                               change_contents = ""
+                                       else
+                                               change_contents = change_contents + "\n" + l.rstrip
+                                       end
+                               else raise RuntimeError, "UNKNOWN state #{field_name}"
+                               end
+                       end
+
+                       # check last package
+                       if not package.nil? then pkglist.push package end
+                       if not change_version.nil? then
+                               if change_log[change_version].nil? then change_log[change_version] = change_contents.strip
+                               else raise RuntimeError, "change log version is duplicated in \"#{file}\" file \n\t#{change_version}"
+                               end
+                       end
+                       pkglist.each {|pkg| pkg.change_log = change_log }
+               end
+               if only_common then return [common_source, common_version, common_maintainer, change_log] end
+               return pkglist
+       end
+
+       def Parser.check_version(version)
+               if not version =~ /^[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*$/ then
+                       raise RuntimeError, "Version format not matched \"#{version}\"\nVersion format must be \"{digit}.{digit}.{digit}\""
+               end
+               return version
+       end
+
+       def Parser.read_changelog(file)
+               return read_multy_pkginfo_from(file,true)[3]
+       end
+
+       def Parser.read_single_pkginfo_from (file)
+               return read_multy_pkginfo_from(file)[0]
+       end
+
+       def Parser.read_repo_pkg_list_from (file)
+               result = {}
+               read_multy_pkginfo_from(file).each { |x| result[x.package_name]=x }
+               return result
+       end
+
+       #for test
+       def Parser.print (array)
+               array.each do |package|
+                       puts package.to_s
+                       puts ""
+               end
+       end
+
+       private
+       def Parser.dep_parser (string_list)
+               dependency_list = []
+               string_list.each do |dep|
+                       #variable initialize
+                       package_name = ""
+                       comp = nil
+                       base_version = nil
+                       target_os_list = []
+                       #string trim
+                       dependency = dep.tr " \t\r\n", ""
+                       #version extract
+                       vs = dependency.index('(')
+                       ve = dependency.index(')')
+                       if not vs.nil? and not ve.nil? then
+                               comp = dependency[(vs+1)..(vs+2)]
+                               base_version = dependency[(vs+3)..(ve-1)]
+                       end
+                       #os list extract
+                       os = dependency.index('[')
+                       oe = dependency.index(']')
+                       if not os.nil? and not oe.nil? then
+                               target_os_list = dependency[(os+1)..(oe-1)].split("|")
+                       end
+                       # package_name extract
+                       pe = dependency.index(/[\]\[\)\(]/)
+                       if pe.nil?
+                               package_name = dependency
+                       else
+                               package_name = dependency[0..pe-1]
+                       end
+                       #package_name check
+                       if not package_name.empty? then
+                               dependency_list.push Dependency.new(package_name,comp,base_version,target_os_list)
+                       end
+               end
+               return dependency_list
+       end
+end
index 24b12ff0dc7fb5a267321e0bbcd7f139a9a2c256..abae33ca89ae713594d5029ff49b9ab6646ff849 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- utils.rb 
+
+ utils.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -25,178 +25,304 @@ limitations under the License.
 Contributors:
 - S-Core Co., Ltd
 =end
+require 'rbconfig'
 
 class Utils
+       STARTUP_INFO_SIZE = 68
+       PROCESS_INFO_SIZE = 16
+       NORMAL_PRIORITY_CLASS = 0x00000020
+
+       def Utils.identify_current_OS()
+               os = "UnsupportedOS"
 
-       if defined?(HOST_OS).nil? then
                case `uname -s`.strip
-                       when "Linux"
-                               HOST_OS = "linux"
-                       when /MINGW32.*/
-                               HOST_OS = "windows"
-                       when "Darwin"
-                               HOST_OS = "darwin"
-                       else
-               end  
+               when "Linux"
+                       if File.exist? "/etc/debian_version" then
+                               arch = (`uname -i`.strip == "x86_64") ? "64" : "32"
+                               os = "ubuntu-#{arch}"
+                       elsif File.exist? "/etc/redhat-release" then
+                               os = "redhat-unknown"
+                       elsif File.exist? "/etc/SuSE-release" then
+                               arch = (`uname -i`.strip == "x86_64") ? "64" : "32"
+                               os = "opensuse-#{arch}"
+                       elsif File.exist? "/etc/mandrake-release" then
+                               os = "mandrake-unknown"
+                       end
+               when "MINGW32_NT-5.1"
+                       progfile_path = Utils.execute_shell_return("echo $PROGRAMFILES","windows")[0].strip
+                       if progfile_path.include?("(x86)") then arch = "64" else arch = "32" end
+                       os = "windows-#{arch}"
+               when "MINGW32_NT-6.1"
+                       progfile_path = Utils.execute_shell_return("echo $PROGRAMFILES","windows")[0].strip
+                       if progfile_path.include?("(x86)") then arch = "64" else arch = "32" end
+                       os = "windows-#{arch}"
+               when "Darwin"
+                       os = "macos-64"
+               end
+
+               return os
        end
 
-       # set static variable in WORKING_DIR, HOME 
-       if defined?(WORKING_DIR).nil? then WORKING_DIR = Dir.pwd end 
-       if defined?(HOME).nil? then 
-               # get home directory, using Dir.chdir
-               Dir.chdir
-               HOME = Dir.pwd
-               Dir.chdir WORKING_DIR 
-       end
-
-    def Utils.create_uniq_name      
-        time = Time.new     
-        # uniq snapshot_name name is year_month_day_hour_min_sec_microsec       
-        return time.strftime("%m%d%H%M%S") + time.usec.to_s()        
-    end
-
-    def Utils.is_url_remote(url)
-        if url.nil? then
-            return false
-        end
-
-        protocol = url.split(':')[0]
-
-        case protocol
-        when "http" then
-            return true
-        else 
-            return false
-        end
-    end
-
-    # if source_ver > target_ver, return -1
-    # if source_ver < target_ver, return 1
-    # if source_ver == target_ver, return 0
-    def Utils.compare_version(source_ver, target_ver)
-        sver = source_ver.split('-')[0]
-        tver = target_ver.split('-')[0]
-
-        arr_sver = sver.split('.')
-        arr_tver = tver.split('.')
-
-        slen = arr_sver.length
-        tlen = arr_tver.length
-        len = tlen 
-
-        if slen > tlen then
-            gap = slen - tlen
-            gap.times do
-                arr_tver.push("0")
-            end
-            len = slen
-        elsif tlen > slen then
-            gap = tlen - slen
-            gap.times do
-                arr_sver.push("0")
-            end
-            len = tlen
-        end 
-
-        len.times do |i|
-            if arr_sver[i].to_i < arr_tver[i].to_i then
-                return 1
-            elsif arr_sver[i].to_i > arr_tver[i].to_i then
-                return -1
-            end
-        end
-
-        return 0
-       end
-
-
-    def Utils.execute_shell(cmd)
-        ret = false
-               if HOST_OS.eql? "windows" then
+
+       def Utils.check_host_OS()
+               if Utils.get_all_OSs().include? HOST_OS then
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       def Utils.get_all_OSs()
+               return ["ubuntu-32","ubuntu-64","windows-32","windows-64","macos-64","opensuse-32", "opensuse-64"]
+       end
+
+
+       def Utils.create_uniq_name
+               time = Time.new
+
+               # uniq snapshot_name name is year_month_day_hour_min_sec_microsec
+               return time.strftime("%m%d%H%M%S") + time.usec.to_s.rjust(6, '0')
+       end
+
+       def Utils.is_url_remote(url)
+               if url.nil? then
+                       return false
+               end
+
+               protocol = url.split(':')[0]
+
+               case protocol
+               when "http" then
+                       return true
+               else
+                       return false
+               end
+       end
+
+       # if source_ver > target_ver, return -1
+       # if source_ver < target_ver, return 1
+       # if source_ver == target_ver, return 0
+       def Utils.compare_version(source_ver, target_ver)
+               sver = source_ver.split('-')[0]
+               tver = target_ver.split('-')[0]
+
+               arr_sver = sver.split('.')
+               arr_tver = tver.split('.')
+
+               slen = arr_sver.length
+               tlen = arr_tver.length
+               len = tlen
+
+               if slen > tlen then
+                       gap = slen - tlen
+                       gap.times do
+                               arr_tver.push("0")
+                       end
+                       len = slen
+               elsif tlen > slen then
+                       gap = tlen - slen
+                       gap.times do
+                               arr_sver.push("0")
+                       end
+                       len = tlen
+               end
+
+               len.times do |i|
+                       if arr_sver[i].to_i < arr_tver[i].to_i then
+                               return 1
+                       elsif arr_sver[i].to_i > arr_tver[i].to_i then
+                               return -1
+                       end
+               end
+
+               return 0
+       end
+
+
+       def Utils.generate_shell_command(cmd, os_category = nil)
+               if os_category.nil? then os_category = get_os_category( HOST_OS ) end
+
+               if os_category == "windows" then
                        mingw_path = "sh.exe -c "
                        cmd = cmd.gsub("\"", "\\\"")
-            cmd = mingw_path + "\"#{cmd}\""
+                       cmd = mingw_path + "\"#{cmd}\""
                end
 
-               system "#{cmd}"
-        if $?.to_i == 0 then ret = true else ret = false end 
-               
+               return cmd
+       end
+
+
+       def Utils.execute_shell(cmd, os_category = nil)
+               ret = false
+
+               # generate command
+               cmd = generate_shell_command(cmd, os_category)
+
+               `#{cmd}`
+               if $?.to_i == 0 then ret = true else ret = false end
+
                return ret
        end
 
 
-    def Utils.execute_shell_return(cmd)
+       def Utils.execute_shell_return(cmd, os_category = nil)
                result_lines = []
 
-               if HOST_OS.eql? "windows" then
-                       mingw_path = "sh.exe -c "
-                       cmd = cmd.gsub("\"", "\\\"")
-            cmd = mingw_path + "\"#{cmd}\""
-               end
+               # generate command
+               cmd = generate_shell_command(cmd, os_category)
 
                # get result
-               IO.popen("#{cmd} 2>&1") { |io|
+               IO.popen("#{cmd} 2>&1") do  |io|
                        io.each do |line|
                                result_lines.push line
                        end
-               }
-               
-        if $?.to_i == 0 then 
+               end
+
+               if $?.to_i == 0 then
                        return result_lines
-               else 
+               else
                        return nil
-               end 
+               end
        end
 
-    def Utils.execute_shell_return_ret(cmd)
-               if HOST_OS.eql? "windows" then
-                       mingw_path = "sh.exe -c "
-                       cmd = cmd.gsub("\"", "\\\"")
-            cmd = mingw_path + "\"#{cmd}\""
-               end
+       def Utils.execute_shell_return_ret(cmd, os_category = nil)
 
-        return `#{cmd}`
-    end
+               # generate command
+               cmd = generate_shell_command(cmd, os_category)
 
-       def Utils.execute_shell_with_log(cmd, log)
+               return `#{cmd}`
+       end
 
-               if HOST_OS.eql? "windows" then
-                       mingw_path = "sh.exe -c "
+
+       # create process and log its all output(stderr, stdout)
+       # can decide whether wait or not
+       def Utils.execute_shell_with_log(cmd, log_path, wait=true)
+
+               if log_path.nil? or log_path.empty? then
+                       return execute_shell_with_stdout(cmd, nil)
+               end
+
+               ruby_path=File.join(Config::CONFIG["bindir"],
+                                                       Config::CONFIG["RUBY_INSTALL_NAME"] +
+                                                       Config::CONFIG["EXEEXT"])
+
+               # call execute
+               os_category = get_os_category( HOST_OS )
+               if os_category == "windows" then
                        cmd = cmd.gsub("\"", "\\\"")
-            cmd = mingw_path + "\"#{cmd}\""
                end
 
+               cmd = "#{ruby_path} \"#{File.expand_path(File.dirname(__FILE__))}/execute_with_log.rb\" \"#{cmd}\" \"#{log_path}\""
+
+               # print log
+               pipe = IO.popen("#{cmd} 2>&1")
+               if wait then
+                       return Process.waitpid2(pipe.pid)
+               else
+                       return [pipe.pid,nil]
+               end
+       end
+
+
+       def Utils.execute_shell_with_stdout(cmd, os_category = nil)
+
+               logger = Logger.new(STDOUT)
+
+               # generate command
+               cmd = generate_shell_command(cmd, os_category)
+
                # print log
-               IO.popen("#{cmd} 2>&1") { |io|
+               pipe = IO.popen("#{cmd} 2>&1") do  |io|
                        io.each do |line|
-                               log.output line
+                               logger.info line
                        end
-               }
-               
-        if $?.to_i == 0 then 
-                       return true 
-               else 
-                       return false 
-               end 
+               end
+
+               return [nil, nil]
        end
 
 
+       def Utils.spawn(cmd, os_category = nil)
+
+               if os_category.nil? then os_category = get_os_category( HOST_OS ) end
+
+               if os_category == "windows" then
+                       create_process(cmd)
+               else
+                       fork do
+                               exec(cmd)
+                       end
+               end
+
+       end
+
+       def Utils.create_process(command,redirStdout="", redirStderr="")
+
+               if redirStdout.length > 0
+                       tmpfile = File.new(redirStdout,"w")
+                       save_stdout = $stdout.clone
+                       $stdout.reopen(tmpfile)
+               end
+
+               if redirStderr.length > 0
+                       tmpfile = File.new(redirStderr,"w")
+                       save_stderr = $stderr.clone
+                       $stderr.reopen(tmpfile)
+               end
+
+               params = [
+                       'L', # IN LPCSTR lpApplicationName
+                       'P', # IN LPSTR lpCommandLine
+                       'L', # IN LPSECURITY_ATTRIBUTES lpProcessAttributes
+                       'L', # IN LPSECURITY_ATTRIBUTES lpThreadAttributes
+                       'L', # IN BOOL bInheritHandles
+                       'L', # IN DWORD dwCreationFlags
+                       'L', # IN LPVOID lpEnvironment
+                       'L', # IN LPCSTR lpCurrentDirectory
+                       'P', # IN LPSTARTUPINFOA lpStartupInfo
+                       'P'  # OUT LPPROCESS_INFORMATION lpProcessInformation
+               ]
+               returnValue = 'I' # BOOL
+
+               startupInfo = [STARTUP_INFO_SIZE].pack('I') + ([0].pack('I') * (STARTUP_INFO_SIZE - 4))
+               processInfo = [0].pack('I') * PROCESS_INFO_SIZE
+
+               createProcess = Win32API.new("kernel32", "CreateProcess", params, returnValue)
+
+               createProcess.call(0, command, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, startupInfo, processInfo)
+
+               if redirStdout.length > 0
+                       $stdout.reopen(save_stdout)
+               end
+
+               save_stdout.close if save_stdout
+
+               if redirStderr.length > 0
+                       $stderr.reopen(save_stderr)
+               end
+
+               save_stderr.close if save_stderr
+
+               ($0 == __FILE__ ) ? processInfo : processInfo.unpack("LLLL")[2]
+       end
+
        def Utils.is_absolute_path(path)
-               if HOST_OS.eql? "linux" or HOST_OS.eql? "darwin" then  
+               if is_unix_like_os( HOST_OS ) then
                        # if path start "/" then absoulte path
                        if path.start_with?("/") then
                                return true
                        else
-                               return false 
+                               return false
                        end
-               elsif HOST_OS.eql? "windows" then 
+               elsif is_windows_like_os( HOST_OS ) then
                        # if path start "c:/" or "D:/" or ... then absoulte path
                        if path =~ /^[a-zA-Z]:[\/]/ then
                                return true
                        else
                                return false
                        end
-               else 
+               else
                        puts "HOST_OS is invalid"
                end
        end
@@ -204,17 +330,313 @@ class Utils
 
        # this will be used on MinGW/MSYS
        def Utils.get_unix_path(path)
-               if HOST_OS.eql? "linux" or HOST_OS.eql? "darwin" then  
+               if is_unix_like_os( HOST_OS ) then
                        return path
-               elsif HOST_OS.eql? "windows" then
+               elsif is_windows_like_os( HOST_OS ) then
                        new_path = path
                        if is_absolute_path( new_path ) then
                                new_path = "/" + new_path[0,1] + new_path[2..-1]
                        end
                        return new_path
-               else 
+               else
                        puts "HOST_OS is invalid"
                        return path
                end
        end
+
+       def Utils.file_lock(lock_file_name)
+               lock_file = File.new(lock_file_name, File::RDWR|File::CREAT, 0644)
+               lock_file.flock(File::LOCK_EX)
+               lock_file.rewind
+               lock_file.flush
+               lock_file.truncate(lock_file.pos)
+
+               return lock_file
+       end
+
+       def Utils.file_unlock(lock_file)
+               lock_file.close
+       end
+
+       def Utils.parse_server_addr(saddr)
+               addr = saddr.split(":")
+               return nil unless addr.length == 2
+               return addr
+       end
+
+       def Utils.parse_ftpserver_url(surl)
+               return nil unless surl.start_with? "ftp://"
+
+               surl = surl[6..-1]
+               parse1 = surl.split("@")
+               return nil unless parse1.length == 2
+
+               idpw = parse1[0]
+               url = parse1[1]
+               parse1 = idpw.split(":")
+               return nil unless parse1.length == 2
+
+               id = parse1[0]
+               passwd = parse1[1]
+               if url.end_with? "/" then url = url.chop end
+
+               parse1 = url.split(":")
+               if parse1.length == 2 then
+                       ip = parse1[0]
+                       port = parse1[1]
+               elsif parse1.length == 1 then
+                       ip = parse1[0]
+                       port = 21
+               else
+                       return nil
+               end
+
+               return [ip, port, id, passwd]
+       end
+
+
+       def Utils.generate_ftp_url(addr, port, username, passwd)
+               return "ftp://#{username}:#{passwd}@#{addr}:#{port}"
+       end
+
+
+       def Utils.extract_a_file(file_path, target_file, path)
+               dirname = File.dirname(file_path)
+               filename = File.basename(file_path)
+               ext = File.extname(filename)
+
+               # path should be unix path if it is used in tar command
+               _package_file_path = Utils.get_unix_path(file_path)
+               _path = Utils.get_unix_path(path)
+
+               case ext
+               when ".zip" then
+                       if not path.nil? then
+                               extract_file_command = "unzip -xo #{_package_file_path} #{target_file} -d #{_path}"
+                       else
+                               extract_file_command = "unzip -xo #{_package_file_path} #{target_file}"
+                       end
+               when ".tar" then
+                       if not path.nil? then
+                               extract_file_command = "tar xf #{_package_file_path} -C #{_path} #{target_file}"
+                       else
+                               extract_file_command = "tar xf #{_package_file_path} #{target_file}"
+                       end
+               end
+
+               # check exit code
+               ret = execute_shell "#{extract_file_command}"
+               if not ret then return false end
+
+               # check result file
+               if not path.nil? then
+                       target_file_path = File.join(path, target_file)
+               else
+                       target_file_path = target_file
+               end
+
+               if not File.exist? target_file_path then
+                       return false
+               else
+                       return true
+               end
+       end
+
+
+       # check if the os is windows-like
+       def Utils.is_windows_like_os(os_name)
+               if os_name.start_with? "windows-" then
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       # check if the os is unix-like
+       def Utils.is_unix_like_os(os_name)
+               if os_name.start_with? "ubuntu-" or
+                       os_name.start_with? "opensuse-" or
+                       os_name.start_with?"macos-" then
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       # check if the os is linux-like
+       def Utils.is_linux_like_os(os_name)
+               if os_name.start_with? "ubuntu-" or
+                       os_name.start_with? "opensuse-" then
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       # check if the os is macos-like
+       def Utils.is_macos_like_os(os_name)
+               if os_name.start_with?"macos-" then
+                       return true
+               else
+                       return false
+               end
+       end
+
+
+       def Utils.get_os_category(os_name)
+               if os_name.start_with? "ubuntu-" or os_name.start_with? "opensuse-" then
+                       return "linux"
+               elsif os_name.start_with?"macos-" then
+                       return "macos"
+               elsif os_name.start_with? "windows-" then
+                       return "windows"
+               else
+                       return os_name
+               end
+       end
+
+
+       def Utils.get_package_name_from_package_file( local_path )
+               filename = File.basename(local_path)
+               if filename =~ /.*_.*_.*\.zip/ then
+                       new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+                       return new_name.split(",")[0]
+               end
+               return nil
+       end
+
+
+       def Utils.get_version_from_package_file( local_path )
+               filename = File.basename(local_path)
+               if filename =~ /.*_.*_.*\.zip/ then
+                       new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+                       return new_name.split(",")[1]
+               end
+               return nil
+       end
+
+
+       def Utils.get_os_from_package_file( local_path )
+               filename = File.basename(local_path)
+               if filename =~ /.*_.*_.*\.zip/ then
+                       new_name = filename.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+                       return new_name.split(",")[2]
+               end
+               return nil
+       end
+
+       def Utils.multi_argument_test( arg, seperator )
+               return ( not arg.end_with? seperator and not arg.split( seperator ).select{|x| x.empty?}.length > 0 )
+       end
+
+       def Utils.directory_emtpy?(dir_path)
+               return (Dir.entries(dir_path).join == "...")
+       end
+
+
+       def Utils.checksum(file_path)
+               if File.exist? file_path then
+                       return Utils.execute_shell_return("shasum -a 256 \"#{file_path}\"")[0].split(" ")[0]
+               else
+                       return nil
+               end
+       end
+
+       def Utils.get_version()
+               version_file = "#{File.dirname(__FILE__)}/../../VERSION"
+
+               if not File.exist? version_file then
+                       return nil
+               end
+
+               f = File.open( version_file, "r" )
+               version = f.readline
+               f.close
+
+               return version
+       end
+
+
+       def Utils.kill_process(base_pid)
+               # stop process execution
+               # NOTE. On MinGW "STOP" option stop whole process, so don't use it 
+               os_category = get_os_category(HOST_OS)
+               if os_category != "windows" then
+                       Process.kill("STOP", base_pid)
+               end
+
+               # get all sub processes # kill&wait
+               sub_pids = get_sub_processes(base_pid)
+               sub_pids.each do  |pid|
+                       Utils.kill_process(pid)
+               end
+
+               begin
+                       Process.kill(9, base_pid)
+                       Process.waitpid2(base_pid)
+               rescue
+                       # do nothing
+               end
+       end
+
+
+       def Utils.get_sub_processes(base)
+               result = []
+
+               # generate pid => ppid hash
+               # NOTE. MinGW does not support "-o" option and has different output format
+               os_category = get_os_category(HOST_OS)
+               if os_category != "windows" then
+                       Hash[*`ps -eo pid,ppid`.scan(/\d+/).map{|x| x.to_i}].each do |pid,ppid|
+                               if ppid == base then
+                                       result.push pid
+                               end
+                       end
+               else
+                       # NOTE.On windows, there two types of pid. win pid, mingw pid
+                       # Sometime these different pids has same value with difference process
+                       # Root of pid is win pid and leaf node is mingw pid
+                       # So, after we get mingw pid, win pid should not be checked.
+                       # gather MinGW/MSYS process id
+                       Hash[*`ps -e`.scan(/^[\s]*(\d+)[\s]+(\d+)/).flatten.map{|x| x.to_i}].each do |pid,ppid|
+                               if ppid == base then
+                                       result.push pid
+                               end
+                       end
+
+                       # gather windows process id if no mingw pid
+                       if result.count == 0 then
+                               require 'rubygems'
+                               require 'sys/proctable'
+                               Sys::ProcTable.ps do  |proc|
+                                       if proc.ppid == base then
+                                               result.push proc.pid
+                                       end
+                               end
+                       end
+               end
+
+               result.uniq!
+               return result
+       end
+
+
+
+       if defined?(HOST_OS).nil? then
+               HOST_OS = Utils.identify_current_OS()
+       end
+
+       # set static variable in WORKING_DIR, HOME
+       if defined?(WORKING_DIR).nil? then WORKING_DIR = Dir.pwd end
+       if defined?(HOME).nil? then
+               # get home directory, using Dir.chdir
+               Dir.chdir
+               HOME = Dir.pwd
+               Dir.chdir WORKING_DIR
+       end
+
+
 end
diff --git a/src/pkg_server/DistSync.rb b/src/pkg_server/DistSync.rb
new file mode 100644 (file)
index 0000000..a79ea4b
--- /dev/null
@@ -0,0 +1,97 @@
+=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 "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..9982274
--- /dev/null
@@ -0,0 +1,240 @@
+=begin
+
+ SocketRegisterListener.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 'socket'
+require 'thread'
+$LOAD_PATH.unshift File.dirname(__FILE__)
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/build_server"
+require "packageServerConfig"
+require "BuildComm"
+require "net/ftp"
+
+# mutax for register operation
+$register_mutex = Mutex.new
+
+class SocketRegisterListener
+
+       # initialize
+       def initialize (parent)
+               @parent_server = parent
+               @thread = nil
+               @finish_loop = false
+               @log = @parent_server.log
+       end
+
+       # start listening
+       def start()
+               @log.info "SocketRegisterListener start"
+               @thread = Thread.new do
+                       main()
+               end
+       end
+
+       # quit listening
+       def stop_listening()
+               @finish_loop = true
+       end
+
+       private
+
+       # thread main
+       def main()
+               @log.info "SocketRegisterListener entering main loop"
+               # server open
+               begin
+                       @comm_server = BuildCommServer.create(@parent_server.port, @log)
+               rescue => e
+                       @log.info "Server creation failed"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+                       return
+               end
+
+               # loop
+               @log.info "Entering Control Listening Loop ... "
+               @finish_loop = false
+               @comm_server.wait_for_connection(@finish_loop) do |req|
+                       begin
+                               handle_job_request( req )
+                       rescue => e
+                               @log.info "error occured in handle_job_request function"
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                       end
+               end
+
+               # quit
+               @comm_server.terminate
+       end
+
+       # wait for job requests
+       def wait_for_job_requests
+               req_list = []
+               req_list.push @tcp_server.accept
+
+               return req_list
+       end
+
+       # handle job request
+       def handle_job_request( req )
+
+               # read request
+               req_line = req.gets
+               if req_line.nil? then return end
+
+               # parse request
+               cmd = ""
+               if req_line.split("|").count > 0 then
+                       cmd = req_line.split("|")[0].strip
+               end
+
+               case cmd
+               when "UPLOAD"
+                       Thread.new do
+                               handle_cmd_upload( req_line, req )
+                       end
+               when "REGISTER"
+                       Thread.new do
+                               handle_cmd_register( req_line, req )
+                       end
+               when "STOP"
+                       handle_cmd_stop( req_line, req )
+               else
+                       @log.error "Received Unknown REQ: #{req_line}"
+               end
+               @log.info "REQ processing done"
+       end
+
+       # "UPLOAD"
+       def handle_cmd_upload( line, req )
+               @log.info "Received File transfer REQ : #{line}"
+
+               BuildCommServer.send_begin(req)
+
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count > 1 then
+                       dock_name = tok[1].strip
+                       incoming_dir = "#{@parent_server.incoming_path}/#{dock_name}"
+                       FileUtils.mkdir_p(incoming_dir)
+               else
+                       incoming_dir = "#{@parent_server.incoming_path}"
+               end
+
+               file_path_list = []
+               begin
+                       @comm_server.receive_file(req, incoming_dir)
+               rescue => e
+                       @log.error "Failed to transfer file"
+                       @log.error e.message
+                       @log.error e.backtrace.inspect
+               end
+               BuildCommServer.send_end(req)
+       end
+
+       # "Register"
+       def handle_cmd_register( line, req )
+               @log.info "Received register REQ : #{line}"
+               BuildCommServer.send_begin(req)
+
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 3 then
+                       @log.error "Received Wrong REQ : #{line}"
+                       BuildCommServer.send(req, "ERROR|Invalid REQ format")
+                       return
+               end
+               dist_name = tok[1].strip
+
+               if tok[2].start_with? "DOCK" then
+                       dock_name = tok[3]
+                       idx = 4
+               else
+                       dock_name = ""
+                       idx = 2
+               end
+
+               file_path_list = []
+
+               while idx < tok.length do
+                       if dock_name.empty? then
+                               file_path_list.push "#{@parent_server.incoming_path}/#{tok[idx]}"
+                       else
+                               file_path_list.push "#{@parent_server.incoming_path}/#{dock_name}/#{tok[idx]}"
+                       end
+                       idx = idx + 1
+               end
+               # register mutex
+               $register_mutex.synchronize do
+                       begin
+                               @parent_server.reload_dist_package()
+                               snapshot_name = @parent_server.register( file_path_list, dist_name, true, false, true)
+                               BuildCommServer.send(req,"SUCC|#{snapshot_name}")
+                       rescue => e
+                               @log.error "register failed"
+                               @log.error e.message
+                               @log.error e.backtrace.inspect
+                               BuildCommServer.send(req, "ERROR|#{e.message}")
+                               @parent_server.release_lock_file
+                               return
+                       end
+               end
+
+               if not dock_name.empty? then
+                       FileUtils.rm_rf "#{@parent_server.incoming_path}/#{dock_name}"
+               end
+
+               BuildCommServer.send_end(req)
+       end
+
+       # "STOP"
+       def handle_cmd_stop( line, req )
+               @log.info "Received STOP REQ"
+
+               BuildCommServer.send_begin(req)
+
+               tok = line.split("|").map { |x| x.strip }
+               if tok.count < 2 then
+                       @log.error "Received Wrong REQ : #{line}"
+                       BuildCommServer.send(req, "ERROR|Invalid REQ format")
+                       return
+               end
+               passwd = tok[1].strip
+
+               if @parent_server.passwd.eql? passwd then
+                       @parent_server.finish = true
+                       @log.info "Package server stop flag set"
+                       BuildCommServer.send(req,"SUCC")
+               else
+                       @log.info "Received stop command, but passwd mismatched : #{passwd}"
+                       BuildCommServer.send(req,"ERROR|Password mismatched!")
+               end
+               BuildCommServer.send_end(req)
+               BuildCommServer.disconnect(req)
+       end
+end
+
index 8bffbd254d55e413368bc27a56351e5d8bb65d33..a3e381531680cf6353757658a09337d790150645 100644 (file)
@@ -1,7 +1,6 @@
-
 =begin
- client.rb 
+
+ client.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -28,1445 +27,1714 @@ Contributors:
 =end
 
 require "fileutils"
+require "thread"
+require "net/ftp"
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/build_server"
 require "downloader"
 require "installer"
-require "serverConfig"
+require "packageServerConfig"
 require "package"
 require "parser"
 require "utils"
 require "log"
 require "Version"
+require "BuildComm"
+require "FileTransferViaFTP"
+require "FileTransferViaDirect"
+
 
+$update_mutex = Mutex.new
+$get_snapshot_mutex = Mutex.new
+$filemove_mutex = Mutex.new
 class Client
 
-    # constant
-    SUPPORTED_OS = ["linux", "windows", "darwin"]
-    PKG_LIST_FILE_PREFIX = "pkg_list_"
-    INSTALLED_PKG_LIST_FILE = "installedpackage.list"
-    CONFIG_PATH = "#{$build_tools}/client"
-    PACKAGE_INFO_DIR = ".info"
-    DEFAULT_INSTALL_DIR = "#{Utils::HOME}/build_root"
-    DEFAULT_SERVER_ADDR = "http://172.21.17.55/dibs/unstable"
-    
-    attr_accessor :server_addr, :location, :pkg_hash_os, :is_server_remote, :installed_pkg_hash_loc, :archive_pkg_list, :all_dep_list, :log
-
-    public
-    # initialize
-    # create "remote package hash" and "installed package hash"
-    # @server_addr = server address (can be included distribution, snapshot)
-    # @location = client location (download and install file to this location)
-    def initialize(server_addr, location, logger)
-
-        # create directory
+       # constant
+       PKG_LIST_FILE_PREFIX = "pkg_list_"
+       INSTALLED_PKG_LIST_FILE = "installedpackage.list"
+       CONFIG_PATH = "#{PackageServerConfig::CONFIG_ROOT}/client"
+       PACKAGE_INFO_DIR = ".info"
+       DEFAULT_INSTALL_DIR = "#{Utils::HOME}/build_root"
+       DEFAULT_SERVER_ADDR = "http://172.21.17.55/dibs/unstable"
+       OS_INFO_FILE = "os_info"
+       ARCHIVE_PKG_LIST_FILE = "archive_pkg_list"
+
+       attr_accessor :server_addr, :location, :pkg_hash_os, :is_server_remote, :installed_pkg_hash_loc, :archive_pkg_list, :all_dep_list, :log, :support_os_list, :config_dist_path, :download_path, :tmp_path, :snapshot_path, :snapshots_path, :snapshot_url
+
+       public
+       # initialize
+       # create "remote package hash" and "installed package hash"
+       # @server_addr = server address (can be included distribution, snapshot)
+       # @location = client location (download and install file to this location)
+       def initialize(server_addr, location, logger)
+
+               # set log
+               if logger.nil? or logger.class.to_s.eql? "String" then
+                       @log = DummyLog.new()
+               else
+                       @log = logger
+               end
+
+               # create directory
                if not File.exist? CONFIG_PATH then FileUtils.mkdir_p "#{CONFIG_PATH}" end
 
-        # set default server address, location
-        if server_addr.nil? then server_addr = get_default_server_addr() end
-        if location.nil? then location = get_default_inst_dir() end
-
-        # chop server address, if end with "/"        
-        if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end
-
-        @server_addr = server_addr
-        @location = location
-        @pkg_hash_os = {}
-        @installed_pkg_hash_loc = {}
-        @archive_pkg_list = []
-        @all_dep_list = []
-        @is_server_remote = Utils.is_url_remote(server_addr)
-
-        # set log
-        if logger.nil? or logger.class.to_s.eql? "String" then
-           @log = Log.new(logger)
-        else
-           @log = logger
-        end
-
-        FileInstaller.set_logger(@log)
-        FileDownLoader.set_logger(@log)
-
-        # read installed pkg list, and create hash
-        FileUtils.mkdir_p "#{@location}"
-        create_installed_pkg_hash()
-       
-        # readk remote pkg list, and hash list
-        create_remote_pkg_hash(false)
-        @log.info "Initialize - #{server_addr}, #{location}"
-    end
-
-    public
-    # update package list from server
-    def update()
-        if not create_remote_pkg_hash(true) then
-            @log.error "\"#{@server_addr}\" does not have package list file properly."
-            return false
-        end
-        create_default_config(@server_addr)
-        @log.info "Update package list from \"#{@server_addr}\".. OK"
-        return true
-    end
-
-    public
-    # download package
-    def download(pkg_name, os, trace)
-
-        dependent_pkg_list = []
-
-        # get dependent list
-        if trace then
-            dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, false)
-            if dependent_pkg_list.nil? then
-                @log.error "Failed to get dependency for \"#{pkg_name}\" package"
-                return false
-            end
-        else dependent_pkg_list = [pkg_name] end
-
-        surl = nil
-        addr_arr = @server_addr.split('/')
-        if addr_arr[-2].eql? "snapshots" then
-            surl = @server_addr + "/../.."
-        else 
-            surl = @server_addr
-        end
-
-        # download files
-        file_local_path = []
-        dependent_pkg_list.each do |p|
-            pkg_path = get_attr_from_pkg(p, os, "path")
-            pkg_ver = get_attr_from_pkg(p, os, "version")
-            url = surl + pkg_path
-            filename = pkg_path.split('/')[-1]
-            if not FileDownLoader.download(url, @location) then
-                @log.error "Failed download #{pkg_name} [#{pkg_ver}]"
-                return nil
-            end
-
-            file_local_path.push(File.join(@location, filename))
-            @log.info "Downloaded \"#{pkg_name} [#{pkg_ver}]\" package file.. OK"
-            @log.info "  [path : #{file_local_path.join(", ")}]"
-        end
-
-        return file_local_path
-    end
-
-    public
-    # download source package
-    def download_source(pkg_name, os)
-
-        # get source file path
-        src_path = get_attr_from_pkg(pkg_name, os, "src_path")
-        if src_path.nil? or src_path.empty? then
-            @log.error "#{pkg_name} package does not have source"
-            return nil
-        end  
-        file_url = nil
-
-        addr_arr = @server_addr.split('/')
-        if addr_arr[-2].eql? "snapshots" then
-            surl = @server_addr + "/../.." + src_path
-        else 
-            surl = @server_addr + src_path
-        end
-
-        # download file
-        filename = src_path.split('/')[-1]
-        if not FileDownLoader.download(surl, @location) then
-            @log.error "Failed download #{pkg_name} source"
-            return nil
-        end
-        file_local_path = File.join(@location, filename)
-        @log.info "Downloaded source of #{pkg_name} package.. OK"
-        @log.info "  [path : #{file_local_path}]"
-
-        return file_local_path
-    end
-    
-    public
-    # download dependent source
-    def download_dep_source(file_name)
-
-        file_url = nil
-
-        addr_arr = @server_addr.split('/')
-        if addr_arr[-2].eql? "snapshots" then
-            file_url = @server_addr + "/../../source/" + file_name
-        else 
-            file_url = @server_addr + "/source/#{file_name}"
-        end
-        if not FileDownLoader.download(file_url, @location) then
-            @log.error "Failed download #{file_name}"
-            return nil
-        end
-        file_local_path = File.join(@location, file_name)
-        @log.info "Downloaded \"#{file_name}\" source file.. OK"
-        @log.info "  [path : #{file_local_path}]"
-
-        return file_local_path
-    end
-
-    public
-    # check archive file
-    def check_archive_file(file_name)
-
-        result = false
-        filename = "archive_pkg_list"
-        local_file_path = File.join(CONFIG_PATH, filename)
-        if File.exist? local_file_path then
-            File.open(local_file_path, "r") do |f|
-                f.each_line do |l|
-                    if l.strip.eql? file_name.strip then 
-                        result = true
-                        break
-                    end     
-                end
-            end
-        end
-        return result
-    end
-
-    public
-    # upload package
-    def upload(ssh_alias, id, binary_path_list, source_path_list, verify)
-
-        # check source path list
-        if source_path_list.nil? or source_path_list.empty? then
-            @log.error "source package path should be set."
-            return nil
-        end
-
-        # verify ssh alias
-        verify = false
-        hostfound = false
-        sshconfig = "#{Utils::HOME}/.ssh/config"
-        File.open(sshconfig, "r") do |f|
-            f.each_line do |l|
-                if l.strip.upcase.start_with? "HOST" then
-                    al = l.strip.split(' ')[1].strip
-                    if al.eql? ssh_alias then hostfound = true
-                    else next end
-                end
-            end
-        end
-
-        if not hostfound then
-            @log.error "\"#{ssh_alias}\" does not exist in \".ssh/config\" file"
-            return nil
-        end
-
-        # get distribution from server addr 
-        dist = get_distribution()
-        if dist.nil? then
-            @log.error "Distribution is nil"
-            return nil
-        end
-
-        serveraddr = @server_addr
-        snapshot = nil
-        if serveraddr.include? "snapshots" then snapshot = serveraddr.split("/")[-1] end
-
-        # set server homd directory
-        server_home = `ssh #{ssh_alias} pwd`
-               server_home = server_home.strip
-
-        # set "pkg-svr" file path 
-               # if pkg-svr exist in path then using pkg-svr
-        result = `ssh #{ssh_alias} which pkg-svr`
-        if not( result.nil? or result.empty? or result.strip.empty? ) then 
-                               pkg_svr = "pkg-svr"
+               # set default server address, location
+               if server_addr.nil? then server_addr = get_default_server_addr() end
+               if location.nil? then location = get_default_inst_dir() end
+
+               # chop server address, if end with "/"
+               if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end
+
+               @snapshot_path = nil
+               @snapshot_url = false
+
+               if is_snapshot_url(server_addr) then
+                       @snapshot_url = true
+                       @server_addr, @snapshot_path = split_addr_and_snapshot(server_addr)
+               else
+                       @server_addr = server_addr
+               end
+
+               @location = location
+               @pkg_hash_os = {}
+               @installed_pkg_hash_loc = {}
+               @archive_pkg_list = []
+               @all_dep_list = []
+               @is_server_remote = Utils.is_url_remote(server_addr)
+               @support_os_list = []
+               @config_dist_path = CONFIG_PATH + "/" + get_flat_serveraddr
+               @download_path = @config_dist_path + "/downloads"
+               @tmp_path = @config_dist_path + "/tmp"
+               @snapshots_path = @config_dist_path + "/snapshots"
+
+               # create directory
+               if not File.exist? @config_dist_path then FileUtils.mkdir_p "#{@config_dist_path}" end
+               if not File.exist? @download_path then FileUtils.mkdir_p "#{@download_path}" end
+               if not File.exist? @snapshots_path then FileUtils.mkdir_p "#{@snapshots_path}" end
+               if not File.exist? @tmp_path then FileUtils.mkdir_p "#{@tmp_path}" end
+
+               # read installed pkg list, and create hash
+               if not File.exist? @location then FileUtils.mkdir_p "#{@location}" end
+               @log.info "Update local package list.. [#{@location}]"
+               read_installed_pkg_list()
+
+               # read remote pkg list, and hash list
+               @log.info "Update remote package list and supported os list.."
+               update()
+               @log.info "Initialize - #{server_addr}, #{location}"
+       end
+
+       public
+       # update package list from server
+       def update()
+               if not @snapshot_url then
+                       $get_snapshot_mutex.synchronize do
+                               @snapshot_path = get_lastest_snapshot(@is_server_remote)
+                       end
+               end
+               @log.info "The lastest snapshot : #{@snapshot_path}"
+               if @snapshot_path.nil? then
+                       @log.warn "Failed to get the lastest package list"
+                       @snapshot_path = ""
+               end
+
+               exists_snapshot = false
+               if is_snapshot_exist(@snapshot_path) then
+                       @log.info "Snapshot information is already cached [#{get_pkglist_path()}]"
+                       exists_snapshot = true
+               else
+                       @log.info "Snapshot information is not cached"
+               end
+
+               list_path = get_pkglist_path()
+               if list_path.nil? then
+                       @log.error "Failed to get package list path"
+                       return false
+               end
+
+               clean_list()
+
+               if exists_snapshot then
+                       read_supported_os_list(list_path)
+                       read_remote_pkg_list(list_path)
+                       read_archive_pkg_list(list_path)
+               else
+                       $update_mutex.synchronize do
+                               uniq_name = Utils.create_uniq_name
+                               tmp_dir = File.join(@config_dist_path, uniq_name)
+                               FileUtils.mkdir_p tmp_dir
+                               if not download_os_list(@is_server_remote, tmp_dir) then
+                                       @log.error "\"#{@server_addr}\" does not have supported os list file properly."
+                                       Utils.execute_shell("rm -rf #{tmp_dir}")
+                                       return false
+                               else read_supported_os_list(tmp_dir) end
+
+                               if not download_pkg_list(@is_server_remote, tmp_dir) then
+                                       @log.error "\"#{@server_addr}\" does not have package list file properly."
+                                       Utils.execute_shell("rm -rf #{tmp_dir}")
+                                       return false
+                               else read_remote_pkg_list(tmp_dir) end
+
+                               if not download_archive_pkg_list(@is_server_remote, tmp_dir) then
+                                       @log.error "\"#{@server_addr}\" does not have archive package list file properly. This error can be ignored"
+                               else read_archive_pkg_list(tmp_dir)     end
+                               Utils.execute_shell("mv #{tmp_dir} #{list_path}")
+                               @log.info "Moved \"#{tmp_dir}\" to"
+                               @log.info "  \"#{list_path}\""
+                               # tmp_dir should be removed  whether mv command is failed
+                               Utils.execute_shell("rm -rf #{tmp_dir}")
+                               remove_snapshots()
+                       end
+               end
+
+               $update_mutex.synchronize do
+                       create_default_config(@server_addr)
+                       @log.info "Update package list from \"#{@server_addr}\".. OK"
+               end
+
+               return true
+       end
+
+       private
+       def clean_list()
+               @pkg_hash_os.clear
+               @archive_pkg_list.clear
+               @support_os_list.clear
+               @log.info "Cleard package list, supported os list.. OK"
+       end
+
+       public
+       # download package
+       def download(pkg_name, os, trace, loc = nil)
+
+               if loc.nil? then loc = @location end
+
+               if not File.exist? loc then FileUtils.mkdir_p "#{loc}" end
+
+               dependent_pkg_list = []
+
+               # get dependent list
+               if trace then
+                       dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, true)
+                       if dependent_pkg_list.nil? then
+                               @log.error "Failed to get dependency for \"#{pkg_name}\" package"
+                               return nil
+                       end
+               else dependent_pkg_list = [pkg_name] end
+
+               surl = @server_addr
+               # download files
+               file_local_path = []
+               dependent_pkg_list.each do |p|
+                       pkg_name = get_attr_from_pkg(p, os, "name")
+                       pkg_path = get_attr_from_pkg(p, os, "path")
+                       pkg_ver = get_attr_from_pkg(p, os, "version")
+                       pkg_checksum = get_attr_from_pkg(p, os, "checksum")
+                       pkg_size = get_attr_from_pkg(p, os, "size")
+                       if pkg_path.nil? or pkg_ver.nil? then
+                               @log.error "\"#{p}\" package does not exist in package server. If it exist in package server, then try \"pkg-cli update\""
+                               return nil
+                       end
+                       url = surl + pkg_path
+                       filename = pkg_path.split('/')[-1]
+
+                       if not FileDownLoader.download(url, loc, @log) then
+                               @log.error "File Download Failed!!"
+                               @log.error "* #{url} -> #{loc}"
+                               return nil
+                       end
+
+                       file_path = File.join(loc, filename)
+                       file_local_path.push(file_path)
+               end
+
+               if trace then
+                       @log.info "Downloaded \"#{pkg_name}\" package with all dependent packages.. OK"
+               end
+               @log.info "  [path: #{file_local_path.join(", ")}]"
+
+               return file_local_path
+       end
+
+       private
+       def remove_downloaded_pkgs(pkg_name, os)
+               pkg_file_prefix = "#{@download_path}/#{pkg_name}_*_#{os}.zip"
+               pkg_files = Dir[pkg_file_prefix].sort_by { |f| File.mtime(f) }.reverse
+
+               if not pkg_files.nil? and pkg_files.length >= 4 then
+                       Utils.execute_shell("rm -rf #{pkg_files[3..-1].join(" ")}")
+                       @log.info "Removed old package files.."
+                       @log.info "  * #{pkg_files[3..-1].join(", ")}"
+               end
+       end
+
+       private
+       def move_downloaded_pkg(filepath, distpath)
+               if filepath.nil? or filepath == "" then return nil end
+               filename = filepath.split('/')[-1]
+               if not File.exist? distpath then FileUtils.mkdir_p "#{distpath}" end
+               distfile = File.join(distpath, filename)
+               @log.info "Moving \"#{filename}\" to download cache directory"
+               @log.info "  [path: #{distpath}]"
+               $filemove_mutex.synchronize do
+                       if not File.exist? distfile then
+                               Utils.execute_shell("mv #{filepath} #{distfile}")
+                       else
+                               Utils.execute_shell("rm -f #{filepath}")
+                               return distfile
+                       end
+               end
+
+               if File.exist? distfile then return distfile
                else
-                       # if pkg-svr not exist in path then try ~/tizen_sdk/dev_tools/pkg-svr
-                       result = `ssh #{ssh_alias} which #{server_home}/tizen_sdk/dev_tools/pkg-svr`
-               if not( result.nil? or result.empty? or result.strip.empty? ) then 
-                               pkg_svr = "#{server_home}/tizen_sdk/dev_tools/pkg-svr"
-                       else 
-               @log.error "Can't find server's pkg-svr command"
-               return nil
+                       @log.info "Failed to move [#{filenamae}] to "
+                       @log.info "  [#{distpath}]"
+                       return nil
+               end
+       end
+
+       private
+       def remove_snapshots()
+               listing_prefix = "#{@snapshots_path}/*"
+               dirs = Dir[listing_prefix].sort_by { |f| File.mtime(f) }.reverse
+
+               if not dirs.nil? and dirs.length >= 20 then
+                       Utils.execute_shell("rm -rf #{dirs[19..-1].join(" ")}")
+                       @log.info "Removed old snapshots.."
+                       @log.info "  * #{dirs[19]} ~ "
+               end
+       end
+
+       private
+       def get_cached_filepath(pkg_filename, pkg_checksum, pkg_size)
+
+               cached_filepath = "#{@download_path}/#{pkg_filename}"
+               if File.exist? cached_filepath then
+                       checksum = `sha256sum #{cached_filepath}`.split(" ")[0]
+                       size = `du -b #{cached_filepath}`.split[0].strip
+                       if checksum.eql? pkg_checksum and size.eql? pkg_size then
+                               return cached_filepath
+                       end
+               end
+               return nil
+       end
+
+       public
+       # download dependent source
+       def download_dep_source(file_name)
+
+               file_url = @server_addr + "/source/#{file_name}"
+               if not FileDownLoader.download(file_url, @location, @log) then
+                       @log.error "Failed download #{file_name}"
+                       return nil
+               end
+               file_local_path = File.join(@location, file_name)
+               @log.info "Downloaded \"#{file_name}\" source file.. OK"
+               @log.info "  [path: #{file_local_path}]"
+
+               return file_local_path
+       end
+
+       public
+       # upload package
+       def upload(ip, port, binary_path_list, ftp_addr=nil, ftp_port=nil, ftp_username=nil, ftp_passwd=nil)
+
+               # check ip and port
+               if ip.nil? or port.nil? then
+                       @log.error "Ip and port should be set."
+                       return nil
+               end
+
+               # check binary path list
+               if binary_path_list.nil? or binary_path_list.empty? then
+                       @log.error "Binary package path should be set."
+                       return nil
+               end
+
+               # create unique dock number
+               dock = Utils.create_uniq_name()
+
+               # upload file
+               binary_list = []
+               binary_path_list.each do |bpath|
+                       filename = File.basename(bpath)
+                       client = BuildCommClient.create(ip, port, @log)
+
+                       if client.nil? then
+                               @log.error "Failed to create BuildCommClient instance.."
+                               return nil
+                       end
+
+                       @log.info "Send ready REQ..  [UPLOAD]"
+                       result = client.send("UPLOAD|#{dock}")
+                       if not result then
+                               @log.error "Failed to send ready REQ.."
+                               return nil
+                       end
+
+                       begin
+                               if not ftp_addr.nil? then
+                                       transporter=FileTransferFTP.new(@log, ftp_addr, ftp_port, ftp_username, ftp_passwd)
+                               else
+                                       transporter=FileTransferDirect.new(@log)
+                               end
+
+                               result = client.send_file(bpath, transporter)
+                       rescue => e
+                               @log.error "FTP failed to put file (exception)"
+                               @log.error "#{e.message}"
+                               @log.error e.backtrace.inspect
+                               return nil
+                       end
+
+                       if not result then
+                               @log.error "FTP failed to put file (result is false)"
+                               return nil
+                       end
+
+                       client.terminate
+                       binary_list.push(filename)
+               end
+
+               # register file
+               if not binary_list.empty? then
+                       client = BuildCommClient.create(ip, port, @log)
+                       dist = get_distribution
+                       if dist.empty? then
+                               @log.error "Distribution is empty.."
+                               return nil
+                       end
+
+                       @log.info "Send register message..  [REGISTER|#{dist}|DOCK|#{dock}|#{binary_list.join("|")}]"
+                       snapshot = nil
+                       if client.send "REGISTER|#{dist}|DOCK|#{dock}|#{binary_list.join("|")}" then
+                               result = client.read_lines do |l|
+                                       line = l.split("|")
+                                       if line[0].strip == "ERROR" then
+                                               @log.error l.strip
+                                               break
+                                       elsif line[0].strip == "SUCC" then
+                                               snapshot = line[1].strip
+                                       end
+                               end
+
+                               if not result or snapshot.nil? then
+                                       @log.error "Failed to register! #{client.get_error_msg()}"
+                                       return nil
+                               end
+                       end
+
+                       client.terminate
+                       snapshot = @server_addr + "/snapshots/" + snapshot
+                       @log.info "Registered successfully!  [#{binary_path_list.join("|")}]"
+                       if snapshot.empty? then
+                               @log.error "Failed to generate snapshot"
+                       end
+               end
+
+               return snapshot
+       end
+
+       private
+       # verify package before uploading
+       def verify_upload(pkg_name, pkg_path)
+
+               manifest_file = "pkginfo.manifest"
+               uniq_name = Utils.create_uniq_name
+               path = Utils::HOME + "/tmp/#{uniq_name}"
+               if not File.exist? path then FileUtils.mkdir_p "#{path}" end
+               begin
+                       if not FileInstaller.extract_a_file(pkg_path, manifest_file, path, @log) then
+                               @log.error "The \"pkginfo.manifest\" file does not exist in \"#{pkg_path}\""
+                               return false
+                       end
+                       manifest_path = File.join(path, manifest_file)
+                       pkg = Parser.read_single_pkginfo_from manifest_path
+                       if File.exists? manifest_path then FileUtils.rm_f(manifest_path) end
+                       FileUtils.remove_dir(path, true)
+               rescue Interrupt
+                       @log.error "Client: Interrupted.."
+                       FileUtils.remove_dir(path, true)
+                       @log.info "Removed #{path}"
+                       raise Interrupt
+               rescue RuntimeError => e
+                       @log.error( e.message, Log::LV_USER)
+                       FileUtils.remove_dir(path, true)
+                       @log.info "Removed #{path}"
+                       return false
+               end
+               new_pkg_ver = pkg.version
+               new_pkg_install_dep_list = pkg.install_dep_list
+               os = pkg.os
+
+               list = get_all_reverse_install_dependent_packages_remote(pkg_name, os, true)
+
+               if not list.nil? then
+                       list.each do |p|
+                               ilist = get_attr_from_pkg(p, os, "install_dep_list")
+                               if ilist.nil? then next end
+                               ilist.each do |l|
+                                       if l.package_name.eql? pkg_name then
+                                               if not l.match? new_pkg_ver then
+                                                       @log.error "\"#{p}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})"
+                                                       return false
+                                               end
+                                       end
+                               end
+                       end
+               end
+
+               if not new_pkg_install_dep_list.nil? then
+                       new_pkg_install_dep_list.each do |l|
+                               if not check_remote_pkg(l.package_name, os) then
+                                       @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version}), but \"#{l.package_name}\" is not exist on server"
+                                       return false
+                               end
+                               rver = get_attr_from_pkg(l.package_name, os, "version")
+                               if not l.match? rver then
+                                       @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})"
+                                       return false
+                               end
                        end
-        end
-        pkg_svr = "#{server_home}/tizen_sdk/dev_tools/pkg-svr"
-
-        # set incoming directory (~/.build_tools/pkg_server/#{id}/incoming)        
-        incoming_path = "#{server_home}/.build_tools/pkg_server/#{id}/incoming"
-
-        # set pkg-svr register command
-        register_command = "#{pkg_svr} register -i #{id} -d #{dist}"
-
-        # upload source package (scp)
-        server_src_pkg_list_command = "\""
-        source_path_list.each do |spath|
-            # set source package file path for server filesystem
-            src_file_name = File.basename(spath)
-            server_src_pkg_path = "#{incoming_path}/#{src_file_name}"
-            server_src_pkg_list_command = server_src_pkg_list_command + server_src_pkg_path + ","
-            # upload source package
-            if File.exist? spath then
-                system "scp #{spath} #{ssh_alias}:#{server_src_pkg_path}"
-            else
-                @log.error "#{spath} file does not exist"
-                return nil
-            end
-        end
-
-        server_src_pkg_list_command = server_src_pkg_list_command.strip
-        if server_src_pkg_list_command.end_with? "," then
-            server_src_pkg_list_command = server_src_pkg_list_command.chop + "\""
-        else
-            server_src_pkg_list_command = server_src_pkg_list_command + "\""
-        end
-
-        # add src package list to register command
-        register_command = register_command + " -s #{server_src_pkg_list_command} -g"
-
-        # upload binary package (scp)
-        if not binary_path_list.nil? then
-            server_bin_pkg_list_command = "\""
-            binary_path_list.each do |bpath|
-                bin_file_name = File.basename(bpath)
-                bin_pkg_name = bin_file_name.split("_")[0]
-                if verify then
-                    if not verify_upload(bin_pkg_name, bpath) then
-                        @log.error "Failed to verify \"#{bpath}\" file"
-                        return nil
-                    end
-                end
-
-                server_bin_pkg_path = "#{incoming_path}/#{bin_file_name}"
-                server_bin_pkg_list_command = server_bin_pkg_list_command + server_bin_pkg_path + ","
-                # upload binary package
-                if File.exist? bpath then
-                    Utils.execute_shell("cd #{File.dirname(bpath)};scp #{File.basename(bpath)} #{ssh_alias}:#{server_bin_pkg_path}")
-                else
-                    @log.error "#{bpath} file does not exist"
-                    return nil
-                end
-            end
-
-            server_bin_pkg_list_command = server_bin_pkg_list_command.strip
-            if server_bin_pkg_list_command.end_with? "," then
-                server_bin_pkg_list_command = server_bin_pkg_list_command.chop + "\""
-            else 
-                server_bin_pkg_list_command = server_bin_pkg_list_command + "\""
-            end
-
-            # add bin package list to register command
-            register_command = register_command + " -p #{server_bin_pkg_list_command}"
-        end
-
-        @log.info "register_command : #{register_command}"
-               
-        # register packages to server
-        result = `ssh #{ssh_alias} #{register_command}`
-        if result.strip.include? "Error occured" then 
-            puts result
-            return nil 
-        end
-
-        # parsing snapshot url to show user
-        serveraddr = @server_addr
-        arr = serveraddr.split("/")
-        if serveraddr.include? "snapshots" then sid = arr[-4]
-        else sid = arr[-2] end
-        i = serveraddr.index(sid)
-        serveraddr = serveraddr[0..i-1]
-        serveraddr = serveraddr + id + "/" + dist
-
-        addr = []
-        result2 = ""
-        arr_re = result.split("\n")
-        arr_re.each do |l|
-            l = l.strip
-            if l.start_with? "snapshot is generated :" then
-                addr = l.split(":")[1].split("/")
-                if addr.include? dist then
-                    i = addr.index(dist)
-                    addr = addr[i+1..-1]
-                    str = ""
-                    addr.each do |l| str = str + "/" + l end
-                    str = serveraddr.strip + str
-                    result2 = result2 + str +"\n"
-                end
-            end
-        end
-
-        @log.info "Upload packages.. OK"
-        @log.info "  [#{binary_path_list.join(", ")}]"
-        @log.info "  [#{source_path_list.join(", ")}]"
-        return result2
-    end
-
-    private
-    # verify package before uploading
-    def verify_upload(pkg_name, pkg_path)
-
-        manifest_file = "pkginfo.manifest"
-        uniq_name = Utils.create_uniq_name
-        path = Utils::HOME + "/tmp/#{uniq_name}"
-        FileUtils.mkdir_p "#{path}"
-        if not FileInstaller.extract_specified_file(pkg_path, manifest_file, path) then
-            @log.error "The \"pkginfo.manifest\" file does not exist in \"#{pkg_path}\""
-            return false
-        end
-        manifest_path = File.join(path, manifest_file)
-        pkg_hash = Parser.read_pkg_list(manifest_path)
-        FileUtils.rm_f(manifest_path)
-        FileUtils.remove_dir(path, true)
-
-        new_pkg_ver = pkg_hash[pkg_name].version
-        new_pkg_install_dep_list = pkg_hash[pkg_name].install_dep_list
-        os = pkg_hash[pkg_name].os
-
-        list = get_all_reverse_install_dependent_packages_remote(pkg_name, os, true)
-
-        if not list.nil? then 
-            list.each do |p|
-                ilist = get_attr_from_pkg(p, os, "install_dep_list")
-                if ilist.nil? then next end
-                ilist.each do |l|
-                    if l.package_name.eql? pkg_name then
-                        if not l.match? new_pkg_ver then
-                            @log.error "\"#{p}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})"
-                            return false
-                        end
-                    end
-                end
-            end
-        end
-
-        if not new_pkg_install_dep_list.nil? then
-            new_pkg_install_dep_list.each do |l|
-                if not check_remote_pkg(l.package_name, os) then
-                    @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version}), but \"#{l.package_name}\" is not exist on server"
-                    return false
-                end
-                rver = get_attr_from_pkg(l.package_name, os, "version")
-                if not l.match? rver then
-                    @log.error "\"#{pkg_name}\" package has following install dependency : #{l.package_name} (#{l.comp} #{l.base_version})"
-                    return false
-                end
-            end
-        end
-
-        @log.info "Passed to verify packages for uploading.. OK"
-        return true
-    end
-
-    private    
-    # get distribution
-    def get_distribution()
-        server = @server_addr
-        if server.nil? or server.empty? then
-            @log.error "Server addr is nil"
-            return nil
-        end
-
-        dist = ""
-        server_arr = server.split("/")
-        if server_arr.include? "snapshots" then
-            i = server_arr.index("snapshots")
-            dist = server_arr[i-1]
-        else dist = File.basename(server) end
-
-        return dist
-    end
-
-    public
+               end
+
+               @log.info "Passed to verify packages for uploading.. OK"
+               return true
+       end
+
+       private
+       # get distribution
+       def get_distribution()
+               server = @server_addr
+               if server.nil? or server.empty? then
+                       @log.error "Server addr is nil"
+                       return nil
+               end
+
+               dist = ""
+               dist = File.basename(server)
+
+               return dist
+       end
+
+       private
+       def get_flat_serveraddr()
+               server = @server_addr
+               if server.nil? or server.empty? then
+                       @log.error "Server addr is nil"
+                       @log.error "check sync_pkg_servers table pkgsvr_url column is null"
+                       return "nil"
+               end
+
+               server = server.delete ".:/@"
+               return server
+       end
+
+       public
        # install package
-    # install all install dependency packages
-    def install(pkg_name, os, trace, force)
-
-        if trace.nil? then trace = true end
-        if force.nil? then force = false end
-
-        # check meta package
-        is_meta_pkg = check_meta_pkg(pkg_name, os)
-        if is_meta_pkg then trace = true end
-        
-        pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
-        if pkg_ver.nil? or pkg_ver.empty? then
-            @log.error "#{pkg_name} package does not exist in remote package list"
-            return false
-        end
-
-        compare_result = compare_version_with_installed_pkg(pkg_name, pkg_ver)
-        if not force then
-            case compare_result
-            when -1 then
-                @log.warn "\"#{pkg_name}\" package version is bigger then remote package version"
-                return true
-            when 0 then
-                @log.warn "\"#{pkg_name}\" package version is same with remote package version"
-                return true
-            when 1, 2 then
-            end
-        end
-
-        # if enable trace, crate all dependent package list
-        if trace then
-            dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, force)
-            if dependent_pkg_list.nil? then
-                @log.error "Failed to get dependency for \"#{pkg_name}\" package"
-                return false
-            end
-        else
-            dependent_pkg_list = [pkg_name]
-        end
-
-        # if meta package, dependent list does not need to include self name
-        #if is_meta_pkg then
-        #    dependent_pkg_list.delete(pkg_name.strip)
-        #end
-
-        # TODO: need to compare dependent package version
-        # install packages including dependent packages
-        dependent_pkg_list.each do |pkg|
-            if not install_pkg(pkg, os, force) then 
-                @log.error "#{pkg} does not exist"
-                return false
-            end
-            add_pkg_info(pkg, os)
-        end
-        write_pkg_hash_to_file(nil)
-
-        if trace then
-            @log.info "Installed \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK"
-            @log.info "  [#{dependent_pkg_list.join(" -> ")}]"
-        else
-            @log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
-        end
-        return true
-       end
-
-    public
-    # install local package (ignore dependent packages)
-    def install_local_pkg(pkg_path, force)
-
-        file_name = File.basename(pkg_path)
-        pkg_name = file_name.split('_')[0]
-
-        if not File.exist? pkg_path then
-            @log.error "\"#{pkg_path}\" file does not exist"
-            return false
-        end
-        filename = File.basename(pkg_path)
-        ext = File.extname(filename)
-        if not ext.eql? ".zip" then
-            @log.error "\"#{file_name}\" is not zip file. binary package file should have .zip ext"
-            return false
-        end
-        pkg_name = filename.split("_")[0]
-        type = "binary"
-        manifest_file = "pkginfo.manifest"
-        pkg_config_path = File.join(@location, PACKAGE_INFO_DIR, pkg_name)
-
-        uniq_name = Utils.create_uniq_name
-        path = Utils::HOME + "/tmp/#{uniq_name}"
-        FileUtils.mkdir_p "#{path}"
-        if not FileInstaller.extract_specified_file(pkg_path, manifest_file, path) then
-            @log.error "pkginfo.manifest file does not exist in #{pkg_path}"
-            return false
-        end
-        manifest_path = File.join(path, manifest_file)
-        pkg_hash = Parser.read_pkg_list(manifest_path)
-        new_pkg_ver = pkg_hash[pkg_name].version
-        FileUtils.rm_f(manifest_path)
-        FileUtils.remove_dir(path, true)
-
-        compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
-        if not force then
-            case compare_result
-            when -1 then
-                @log.warn "\"#{pkg_name}\" package version is bigger then remote package version.."
-                return true
-            when 0 then
-                @log.warn "\"#{pkg_name}\" package version is same with remote package version.."
-                return true
-            when 1, 2 then
-            end
-        end
-
-        if check_installed_pkg(pkg_name) then
-            uninstall(pkg_name, false)
-        end
-
-        # install package
-        ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location)
-
-        add_local_pkg_info(pkg_name)
-        write_pkg_hash_to_file(nil)
-
-        @log.info "Installed \"#{pkg_path} [#{new_pkg_ver}]\" file.. OK"
-        return true
-    end
-
-    public
-    # upgrade package
-    def upgrade(os, trace)
-
-        if trace.nil? then trace = true end
-        list = check_upgrade(os)
-
-        if list.empty? or list.nil? then
-            @log.info "There is no packages for upgrading.."
-            return false
-        end
-
-        list.each do |p|
-            if check_installed_pkg(p) then
-                if not uninstall(p, trace) then
-                    @log.error "Failed to uninstall \"#{p}\" package.."
-                    return false
-                end
-            end
-
-            if not install(p, os, trace, false) then
-                @log.error "Failed to install \"#{p}\" package.."
-                return false
-            end
-        end
-
-        @log.info "Upgraded packages from #{@server_addr}.. OK"
-        return true
-    end
-
-    public
-    # check package which will be upgraded
-    def check_upgrade(os)
-
-        update_pkgs = []
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        installed_pkg_hash = installed_pkg_hash_loc[installed_pkg_hash_key]
-        remote_pkg_hash = pkg_hash_os[os]
-        
-        if remote_pkg_hash.nil? then
-            @log.error "There is no remote package list for #{os}. please pkg-cli update"
-            return nil
-        end
-
-        if installed_pkg_hash.nil? then
-            @log.warn "There is no any installed package in \"#{@location}\""
-            return remote_pkg_hash.keys
-        end
-
-        arr_keys = installed_pkg_hash.keys
-        arr_keys.each do |k|
-            installed_ver = get_attr_from_installed_pkg(k, "version")
-            if not check_remote_pkg(k, os) then next end
-            remote_ver = get_attr_from_pkg(k, os, "version")
-            compare_result = compare_version_with_installed_pkg(k, remote_ver)
-            case compare_result
-            when -1 then next
-            when 0 then next
-            when 1 then 
-                @log.output "\"#{k}\" package : #{installed_ver} -> #{remote_ver}"
-                update_pkgs.push(k) 
-            end
-        end
-
-        @log.info "Checked packages for upgrading.. OK"
-        return update_pkgs    
-    end
-
-    public
-    def get_default_server_addr()
-        filepath = "#{CONFIG_PATH}/config"
-        server_addr = nil
-
-        if not File.exist? filepath then create_default_config(nil) end
-        if not File.exist? filepath then
-            @log.error "There is no default server address in #{filepath}"
-            return nil
-        end
-
-        File.open filepath, "r" do |f|
-            f.each_line do |l|
-                if l.strip.start_with? "DEFAULT_SERVER_ADDR :" then
-                    server_addr = l.split("DEFAULT_SERVER_ADDR :")[1].strip
-                break
-                else next end
-            end
-        end
-
-        if server_addr.nil? then create_default_config(DEFAULT_SERVER_ADDR) end
-        return server_addr
-    end
-
-    public
-    # get default path for installing
-    def get_default_inst_dir()
-        return Dir.pwd 
-    end
-
-    private
-    # create default config file (Utils::HOME/.build_tools/client/config)
-    def create_default_config(server_addr)
-        filepath = "#{CONFIG_PATH}/config"
-        if server_addr.nil? then server_addr = DEFAULT_SERVER_ADDR end
-
-        if File.exist? filepath then
-            FileUtils.rm_f(filepath)
-        end
-
-        if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end
-        
-        File.open(filepath, "a+") do |file|
-            file.puts "DEFAULT_SERVER_ADDR : #{server_addr}"
-        end
-    end
-
-    public
-    # uninstall package
-    # trace : if true, uninstall all dependent packages
-    def uninstall(pkg_name, trace)
-
-        type = "binary"
-        pkg_list = []
-        pkg_hash = nil
-
-        if not check_installed_pkg(pkg_name) then
-            @log.error "\"#{pkg_name}\" package is not installed."
-            return false 
-        end
-
-        pkg_ver = get_attr_from_installed_pkg(pkg_name, "version")
-
-        if trace then
-            pkg_list = get_all_reverse_install_dependent_packages(pkg_name, true)
-            if pkg_list.nil? then
-                @log.error "Failed to get \"#{pkg_name}\" package dependency information."
-                return false
-            end
-        else
-            pkg_list.push(pkg_name)
-        end
-
-        pkg_list.each do |p|
-            if not check_installed_pkg(p) then next end
-            if not FileInstaller.uninstall(p, type, @location) then
-                @log.error "Failed uninstall \"#{pkg_name}\" package"
-                return false
-            end
-            pkg_hash = remove_pkg_info(p)
-        end
-
-        if trace then
-            @log.info "Uninstalled \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK"
-            @log.info "  [#{pkg_list.join(" -> ")}]"
-        else
-            @log.info "Uninstalled only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
-        end
-
-        write_pkg_hash_to_file(nil)
-        return true
-    end
-
-    public 
-    # clean
-    def clean(force)
-        if not force then
-            puts "Do you really want to remove \"#{@location}\" path? [yes]"
-            input = $stdin.gets.strip
-            if input.upcase.eql? "YES" then
-                @log.info "Removed \"#{@location}\""
-            else
-                @log.info "Canceled"
-                return
-            end
-        end
-        FileUtils.rm_rf(@location)
-        FileUtils.mkdir_p(@location)
-        @pkg_hash_os.clear
-        @installed_pkg_hash_loc.clear
-        @archive_pkg_list.clear
-        @log.info "Cleaned \"#{@location}\" path.. OK"
-    end
-
-    public
+       # install all install dependency packages
+       def install(pkg_name, os, trace, force)
+
+               ret = install_internal( pkg_name, os, trace, force )
+               return ret
+       end
+
+
+       private
+       def install_internal(pkg_name, os, trace, force)
+
+               if trace.nil? then trace = true end
+               if force.nil? then force = false end
+
+               # check meta package
+               is_meta_pkg = check_meta_pkg(pkg_name, os)
+               if is_meta_pkg then trace = true end
+
+               # compare package version with installed package's
+               pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
+               if pkg_ver.nil? or pkg_ver.empty? then
+                       @log.error "#{pkg_name} package does not exist in remote package list"
+                       return false
+               end
+
+
+               compare_result = compare_version_with_installed_pkg(pkg_name, pkg_ver)
+               if not force then
+                       case compare_result
+                       when -1 then
+                               @log.warn "Checked \"#{pkg_name}\" package version : it is bigger then remote package version"
+                               return true
+                       when 0 then
+                               @log.warn "Checked \"#{pkg_name}\" package version : it is same with remote package version"
+                               return true
+                       when 1, 2 then
+                       end
+               end
+
+               # if enable trace, create all dependent package list
+               if trace then
+                       dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, force)
+                       if dependent_pkg_list.nil? then
+                               @log.error "Failed to get dependency for \"#{pkg_name}\" package"
+                               return false
+                       end
+               else
+                       dependent_pkg_list = [pkg_name]
+               end
+
+               # TODO: need to compare dependent package version
+               # install packages including dependent packages
+               dependent_pkg_list.each do |pkg|
+                       if not install_pkg(pkg, os, force) then
+                               @log.error "#{pkg} does not exist"
+                               return false
+                       end
+                       add_pkg_info(pkg, os)
+               end
+
+               # write installed package information to file
+               write_pkg_hash_to_file(nil)
+
+               if trace then
+                       @log.info "Installed \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK"
+                       @log.info "  [#{dependent_pkg_list.join(" -> ")}]"
+               else
+                       @log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
+               end
+
+               return true
+       end
+
+
+       public
+       # install local package (ignore dependent packages)
+       def install_local_pkg(pkg_path, trace, force, repos_paths = nil)
+
+               ret = install_local_pkg_internal(pkg_path, trace, force, repos_paths)
+               return ret
+       end
+
+
+       private
+       def install_local_pkg_internal(pkg_path, trace, force, repos_paths)
+
+               file_name = File.basename(pkg_path)
+               pkg_name = file_name.split('_')[0]
+
+               if not File.exist? pkg_path then
+                       @log.error "\"#{pkg_path}\" file does not exist"
+                       return false
+               end
+               filename = File.basename(pkg_path)
+               ext = File.extname(filename)
+               if not ext.eql? ".zip" then
+                       @log.error "\"#{file_name}\" is not zip file. binary package file should have .zip ext"
+                       return false
+               end
+               pkg_name = filename.split("_")[0]
+               manifest_file = "pkginfo.manifest"
+
+               uniq_name = Utils.create_uniq_name
+               path = Utils::HOME + "/tmp/#{uniq_name}"
+               if not File.exist? path then FileUtils.mkdir_p "#{path}" end
+               begin
+                       if not FileInstaller.extract_a_file(pkg_path, manifest_file, path, @log) then
+                               @log.error "pkginfo.manifest file does not exist in #{pkg_path}"
+                               return false
+                       end
+                       manifest_path = File.join(path, manifest_file)
+                       pkg = Parser.read_single_pkginfo_from manifest_path
+                       new_pkg_ver = pkg.version
+                       FileUtils.remove_dir(path, true)
+               rescue Interrupt
+                       @log.error "Client: Interrupted.."
+                       FileUtils.remove_dir(path, true)
+                       @log.info "Removed #{path}"
+                       raise Interrupt
+               rescue RuntimeError => e
+                       @log.error( e.message, Log::LV_USER)
+                       FileUtils.remove_dir(path, true)
+                       @log.info "Removed #{path}"
+                       return false
+               end
+
+               compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+               if not force then
+                       case compare_result
+                       when -1 then
+                               @log.warn "Installed \"#{pkg_name}\" package version is bigger.."
+                               return true
+                       when 0 then
+                               @log.warn "Checked \"#{pkg_name}\" package version : it is same with installed package version"
+                               return true
+                       when 1, 2 then
+                       end
+               end
+
+               if check_installed_pkg(pkg_name) then
+                       uninstall(pkg_name, false)
+               end
+
+               if trace then
+                       install_dep_pkgs = pkg.install_dep_list
+                       new_pkg_os = pkg.os
+                       install_dep_pkgs.each do |p|
+                               # check local path first
+                               if not repos_paths.nil? then
+                                       # search
+                                       binpkgs = []
+                                       repos_paths.each do  |repos_path|
+                                               binpkgs += Dir.glob("#{repos_path}/#{p.package_name}_*_#{new_pkg_os}.zip")
+                                       end
+                                       if not binpkgs.empty? then
+                                               if not install_local_pkg_internal(binpkgs[0], true, false, repos_paths) then
+                                                       @log.warn "#{p} package is not installed"
+                                               end
+                                       else
+                                               if not install_internal(p.package_name, new_pkg_os, true, false) then
+                                                       @log.warn "#{p} package is not installed"
+                                               end
+                                       end
+                               else
+                                       if not install_internal(p.package_name, new_pkg_os, true, false) then
+                                               @log.warn "#{p} package is not installed"
+                                       end
+                               end
+                       end
+               end
+
+               # install package
+               ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location, @log)
+
+               if not ret then
+                       @log.error "Install failed \"#{pkg_path} [#{new_pkg_ver}]\" file.. "
+                       return false
+               end
+
+               add_local_pkg_info(pkg_name)
+               write_pkg_hash_to_file(nil)
+
+               @log.info "Installed \"#{pkg_path} [#{new_pkg_ver}]\" file.. OK"
+               return true
+       end
+
+
+       public
+       # upgrade package
+       def upgrade(os, trace)
+
+               if trace.nil? then trace = true end
+               list = check_upgrade(os)
+
+               if list.empty? or list.nil? then
+                       @log.info "There is no packages for upgrading.."
+                       return false
+               end
+
+               list.each do |p|
+                       if check_installed_pkg(p) then
+                               if not uninstall(p, trace) then
+                                       @log.error "Failed to uninstall \"#{p}\" package.."
+                                       return false
+                               end
+                       end
+
+                       if not install_internal(p, os, trace, false) then
+                               @log.error "Failed to install \"#{p}\" package.."
+                               return false
+                       end
+               end
+
+               @log.info "Upgraded packages from #{@server_addr}.. OK"
+               return true
+       end
+
+       public
+       # check package which will be upgraded
+       def check_upgrade(os)
+
+               update_pkgs = []
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               installed_pkg_hash = installed_pkg_hash_loc[installed_pkg_hash_key]
+               remote_pkg_hash = pkg_hash_os[os]
+
+               if remote_pkg_hash.nil? then
+                       @log.error "There is no remote package list for #{os}. please pkg-cli update"
+                       return nil
+               end
+
+               if installed_pkg_hash.nil? then
+                       @log.warn "There is no any installed package in \"#{@location}\""
+                       return remote_pkg_hash.keys
+               end
+
+               arr_keys = installed_pkg_hash.keys
+               arr_keys.each do |k|
+                       installed_ver = get_attr_from_installed_pkg(k, "version")
+                       if not check_remote_pkg(k, os) then next end
+                       remote_ver = get_attr_from_pkg(k, os, "version")
+                       compare_result = compare_version_with_installed_pkg(k, remote_ver)
+                       case compare_result
+                       when -1 then next
+                       when 0 then next
+                       when 1 then
+                               @log.output "\"#{k}\" package : #{installed_ver} -> #{remote_ver}"
+                               update_pkgs.push(k)
+                       end
+               end
+
+               @log.info "Checked packages for upgrading.. OK"
+               return update_pkgs
+       end
+
+       public
+       def get_default_server_addr()
+               filepath = "#{CONFIG_PATH}/config"
+               server_addr = nil
+
+               if not File.exist? filepath then create_default_config(nil) end
+               if not File.exist? filepath then
+                       @log.error "There is no default server address in #{filepath}"
+                       return nil
+               end
+
+               File.open filepath, "r" do |f|
+                       f.each_line do |l|
+                               if l.strip.start_with? "DEFAULT_SERVER_ADDR :" then
+                                       server_addr = l.split("DEFAULT_SERVER_ADDR :")[1].strip
+                                       break
+                               else next end
+                       end
+               end
+
+               if server_addr.nil? then create_default_config(DEFAULT_SERVER_ADDR) end
+               return server_addr
+       end
+
+       public
+       # get default path for installing
+       def get_default_inst_dir()
+               return Dir.pwd
+       end
+
+       private
+       # create default config file (Utils::HOME/.build_tools/client/config)
+       def create_default_config(server_addr)
+               filepath = "#{CONFIG_PATH}/config"
+               if server_addr.nil? then server_addr = DEFAULT_SERVER_ADDR end
+
+               if File.exist? filepath then
+                       FileUtils.rm_f(filepath)
+               end
+
+               if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end
+
+               File.open(filepath, "a+") do |file|
+                       file.puts "DEFAULT_SERVER_ADDR : #{server_addr}"
+               end
+       end
+
+       public
+       # uninstall package
+       # trace : if true, uninstall all dependent packages
+       def uninstall(pkg_name, trace)
+
+               type = "binary"
+               pkg_list = []
+               pkg_hash = nil
+
+               if not check_installed_pkg(pkg_name) then
+                       @log.error "\"#{pkg_name}\" package is not installed."
+                       return false
+               end
+
+               pkg_ver = get_attr_from_installed_pkg(pkg_name, "version")
+
+               if trace then
+                       pkg_list = get_all_reverse_install_dependent_packages(pkg_name, true)
+                       if pkg_list.nil? then
+                               @log.error "Failed to get \"#{pkg_name}\" package dependency information."
+                               return false
+                       end
+               else
+                       pkg_list.push(pkg_name)
+               end
+
+               pkg_list.each do |p|
+                       if not check_installed_pkg(p) then next end
+                       if not FileInstaller.uninstall(p, type, @location, @log) then
+                               @log.error "Failed uninstall \"#{pkg_name}\" package"
+                               return false
+                       end
+                       pkg_hash = remove_pkg_info(p)
+               end
+
+               if trace then
+                       @log.info "Uninstalled \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK"
+                       @log.info "  [#{pkg_list.join(" -> ")}]"
+               else
+                       @log.info "Uninstalled only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
+               end
+
+               write_pkg_hash_to_file(nil)
+               return true
+       end
+
+       public
+       # clean
+       def clean(force)
+               if not force then
+                       puts "Do you really want to remove \"#{@location}\" path? [yes]"
+                       input = $stdin.gets.strip
+                       if input.upcase.eql? "YES" then
+                               @log.info "Removed \"#{@location}\""
+                       else
+                               @log.info "Canceled"
+                               return
+                       end
+               end
+               if File.exist? @location then FileUtils.rm_rf(@location) end
+               FileUtils.mkdir_p(@location)
+               #@pkg_hash_os.clear
+               @installed_pkg_hash_loc.clear
+               #@archive_pkg_list.clear
+               @log.info "Cleaned \"#{@location}\" path.. OK"
+       end
+
+       public
        # get reverse build dependent packages (just 1 depth)
-    def get_reverse_build_dependent_packages(pkg_name, os)
-
-        result = []
-        pkg_hash = @pkg_hash_os[os]
-        pkg_list = pkg_hash.values
-        pkg_list.each do |pkg|
-            pkg.build_dep_list.each do |dep|
-                if dep.package_name.eql? pkg_name and
-                                       not dep.target_os_list.nil? and 
+       def get_reverse_build_dependent_packages(pkg_name, os)
+
+               result = []
+               pkg_hash = @pkg_hash_os[os]
+               if pkg_hash.nil? then return [] end
+               pkg_list = pkg_hash.values
+               pkg_list.each do |pkg|
+                       pkg.build_dep_list.each do |dep|
+                               if dep.package_name.eql? pkg_name and
+                                       not dep.target_os_list.nil? and
                                        dep.target_os_list.include? os then
-                    result.push(pkg.package_name)
-                end
-            end
-        end
+                                       result.push(pkg)
+                               end
+                       end
+               end
 
-        return result
-    end
+               return result
+       end
 
-    public
+       public
        # get reverse source dependent packages (just 1 depth)
-    def get_reverse_source_dependent_packages(pkg_name, os)
-
-        result = []
-        pkg_hash = @pkg_hash_os[os]
-        pkg_list = pkg_hash.values
-        pkg_list.each do |pkg|
-            pkg.source_dep_list.each do |p|
-                if p.package_name.eql? pkg_name then
-                    result.push(pkg.package_name)
-                end
-            end
-        end
-
-        return result
-    end
-
-    public
+       def get_reverse_source_dependent_packages(pkg_name)
+
+               result = []
+               @support_os_list.each do |os|
+                       pkg_hash = @pkg_hash_os[os]
+                       pkg_list = pkg_hash.values
+                       pkg_list.each do |pkg|
+                               pkg.source_dep_list.each do |p|
+                                       if p.package_name.eql? pkg_name then
+                                               result.push(pkg)
+                                       end
+                               end
+                       end
+               end
+
+               return result
+       end
+
+       public
        # get reverse install dependent packages (jush 1 depth)
-    def get_reverse_install_dependent_packages(pkg_name, os)
-
-        result = []
-        pkg_hash = @pkg_hash_os[os]
-        pkg_list = pkg_hash.values
-        pkg_list.each do |pkg|
-            pkg.install_dep_list.each do |p|
-                if p.package_name.eql? pkg_name then
-                    result.push(pkg.package_name)
-                end
-            end
-        end
-
-        return result
-    end
-
-    public
+       def get_reverse_install_dependent_packages(pkg_name, os)
+
+               result = []
+               pkg_hash = @pkg_hash_os[os]
+               pkg_list = pkg_hash.values
+               pkg_list.each do |pkg|
+                       pkg.install_dep_list.each do |p|
+                               if p.package_name.eql? pkg_name then
+                                       result.push(pkg.package_name)
+                               end
+                       end
+               end
+
+               return result
+       end
+
+       public
        # get all build dependent packages (considered build priority, and reverse)
-    def get_build_dependent_packages(pkg_name, os, reverse)
-
-        if not check_remote_pkg(pkg_name, os) then return nil end
-        if reverse.nil? then reverse = true end
-
-        @all_dep_list.clear
-        begin            
-            get_build_dependency_arr(pkg_name, os, 0)
-        # in case of cross build dependency
-        rescue SystemStackError
-            @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
-            return nil
-        end
-
-        max = 0
-        @all_dep_list.each do |p|
-            if p[0].to_i > max then
-                max = p[0].to_i
-            else next end
-        end
-
-        result = []
-        i = 0
-        while i <= max
-            @all_dep_list.each do |p|
-                if p[0].to_i.eql? i then
-                    d = p[1]
-                    remote_os = get_attr_from_pkg(d.package_name, os, "os")
-                    remote_ver = get_attr_from_pkg(d.package_name, os, "version") 
-                    if not d.target_os_list.include? remote_os then
-                        @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.target_os_list.to_s}, but \"#{d.package_name}\" (#{remote_os}) package is in server"
-                        return nil
-                    end
-                    if not d.match? remote_ver then
-                        @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server"
-                        return nil
-                    else result.push(d.package_name) end
-                end
-            end
-            i = i + 1
-        end
-
-        @log.info "Get build dependent packages for #{pkg_name} package.. OK"
-        if reverse then return result.reverse.uniq.push(pkg_name)
-        else return result.uniq.insert(0, pkg_name) end
-    end
-
-    public
+       def get_build_dependent_packages(pkg_name, os, reverse)
+
+               if not check_remote_pkg(pkg_name, os) then return nil end
+               if reverse.nil? then reverse = true end
+
+               @all_dep_list.clear
+               begin
+                       get_build_dependency_arr(pkg_name, os, 0)
+                       # in case of cross build dependency
+               rescue SystemStackError
+                       @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
+                       return nil
+               end
+
+               max = 0
+               @all_dep_list.each do |p|
+                       if p[0].to_i > max then
+                               max = p[0].to_i
+                       else next end
+               end
+
+               result = []
+               i = 0
+               while i <= max
+                       @all_dep_list.each do |p|
+                               if p[0].to_i.eql? i then
+                                       d = p[1]
+                                       remote_os = get_attr_from_pkg(d.package_name, os, "os")
+                                       remote_ver = get_attr_from_pkg(d.package_name, os, "version")
+                                       if not d.target_os_list.include? remote_os then
+                                               @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.target_os_list.to_s}, but \"#{d.package_name}\" (#{remote_os}) package is in server"
+                                               return nil
+                                       end
+                                       if not d.match? remote_ver then
+                                               @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server"
+                                               return nil
+                                       else result.push(d.package_name) end
+                               end
+                       end
+                       i = i + 1
+               end
+
+               @log.info "Get build dependent packages for #{pkg_name} package.. OK"
+               if reverse then return result.reverse.uniq.push(pkg_name)
+               else return result.uniq.insert(0, pkg_name) end
+       end
+
+       public
        # get all install dependent packages (considered install priority, reverse, and force)
-    # reverse : return reverse result
-    # force : install package force
-    def get_install_dependent_packages(pkg_name, os, reverse, force)
-
-        if not check_remote_pkg(pkg_name, os) then return nil end
-        if reverse.nil? then reverse = true end
-
-        @all_dep_list.clear
-        begin            
-            get_install_dependency_arr(pkg_name, os, force, 0)
-        # in case of cross build dependency
-        rescue SystemStackError
-            @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
-            return nil
-        end
-
-        max = 0
-        @all_dep_list.each do |p|
-            if p[0].to_i > max then
-                max = p[0].to_i
-            else next end
-        end
-
-        result = []
-        i = 0
-        while i <= max
-            @all_dep_list.each do |p|
-                if p[0].to_i.eql? i then
-                    d = p[1]
-                    remote_ver = get_attr_from_pkg(d.package_name, os, "version") 
-                    if not d.match? remote_ver then
-                        @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server"
-                        return nil
-                    else result.push(d.package_name) end
-                end
-            end
-            i = i + 1
-        end
-        
-        @log.info "Get install dependent packages for #{pkg_name} package.. OK"
-        if reverse then return result.reverse.uniq.push(pkg_name)
-        else return result.uniq.insert(0, pkg_name) end
-    end
-
-    public
-    # get all reverse install dependent packages (considered reverse install priority for tracing uninstall)
-    def get_all_reverse_install_dependent_packages(pkg_name, reverse)
-
-        if not check_installed_pkg(pkg_name) then return nil end
-        if reverse.nil? then reverse = true end
-
-        begin
-            res = get_all_reverse_install_dependency_arr(pkg_name, 0)
-        rescue SystemStackError
-            @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
-            return nil
-        end
-        res2 = res.split("::")
-        result = []
-        res2.each do |r|
-            result.push(r.split(':')[1])
-        end
-
-        @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK"
-        if reverse then return result.reverse.uniq
-        else return result end
-    end
-
-    public
-    # get all reverse remote dependent packages (considered reverse install priority for tracing uninstall)
-    def get_all_reverse_install_dependent_packages_remote(pkg_name, os, reverse)
-        #if not check_remote_pkg(pkg_name, os) then return nil end
-        if reverse.nil? then reverse = true end
-
-        begin
-            res = get_all_reverse_install_dependency_arr_remote(pkg_name, os, 0)
-        rescue SystemStackError
-            @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
-            return nil
-        end
-        res2 = res.split("::")
-        result = []
-        res2.each do |r|
-            result.push(r.split(':')[1])
-        end
-
-        @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK"
-        if reverse then return result.reverse
-        else return result end
-    end
-
-    public
-    # check package whether to exist in remote server
-    def check_remote_pkg(pkg_name, os)
-
-        pkg_hash = @pkg_hash_os[os]
-        if pkg_hash.nil? then return false end
-        pkg = pkg_hash[pkg_name]
-        if pkg.nil? then
-            @log.warn "There is no \"#{pkg_name}\" remote package information in list"
-            return false
-        end
-
-        return true
-    end
-
-    public
-    # check package whether to exist in installed packages
-    def check_installed_pkg(pkg_name)
-
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
-        if pkg_hash.nil? then return false end
-        pkg = pkg_hash[pkg_name]
-
-        if pkg.nil? then return false end
-        return true
-    end
-
-    public
-    # get attribute from installed package
-    def get_attr_from_installed_pkg(pkg_name, attr)
-
-        if not check_installed_pkg(pkg_name) then return nil end
-        pkg = get_installed_pkg_from_list(pkg_name)
-
-        if pkg.nil? then return nil end
-
-        case attr
-        when "version" then return pkg.version
-        when "source" then return pkg.source
-        when "src_path" then return pkg.src_path
-        when "os" then return pkg.os
-        when "build_dep_list" then return pkg.build_dep_list
-        when "install_dep_list" then return pkg.install_dep_list
-        when "attribute" then return pkg.attribute
-        end
-    end
-
-    public
-    # get attribute from remote package
-    def get_attr_from_pkg(pkg_name, os, attr)
-
-        if not check_remote_pkg(pkg_name, os) then return nil end
-        pkg = get_pkg_from_list(pkg_name, os)
-
-        if pkg.nil? then return nil end
-
-        case attr
-        when "path" then return pkg.path
-        when "source" then return pkg.source
-        when "version" then return pkg.version
-        when "src_path" then return pkg.src_path
-        when "os" then return pkg.os
-        when "build_dep_list" then return pkg.build_dep_list
-        when "install_dep_list" then return pkg.install_dep_list
-        when "attribute" then return pkg.attribute
-        end
-    end
-
-    public
-    # show a package information
-    def show_pkg_info(pkg_name, os)
-        if not check_remote_pkg(pkg_name, os) then
-            @log.error "\"#{pkg_name}\" package does not exist"
-            return ""
-        end
-
-        pkg = get_pkg_from_list(pkg_name, os)
-        return pkg.to_s
-    end
-
-    public
-    # show all packages information 
-    def show_pkg_list(os)
-        pkg_hash = @pkg_hash_os[os]
-        if pkg_hash.nil? then
-            @log.error "\"#{os}\" package list does not exist"
-            return ""
-        end
-
-        pkg_all_list = []
-        pkg_list = pkg_hash.values
-        pkg_list.each do |p|
-            pkg_all_list.push([p.package_name, p.version, p.description])
-        end
-        return pkg_all_list.sort
-    end
-
-    public
-    # show installed package information
-    def show_installed_pkg_info(pkg_name)
-
-        if not check_installed_pkg(pkg_name) then
-            @log.error "\"#{pkg_name}\" package does not exist"
-            return ""
-        end
-
-        pkg = get_installed_pkg_from_list(pkg_name)
-        return pkg.to_s
-    end
-
-    public
-    # show all installed packages information 
-    def show_installed_pkg_list()
-
-        file_path = get_installed_pkg_list_file_path()
-        pkg_hash = @installed_pkg_hash_loc[file_path]
-        if pkg_hash.nil? then
-            @log.error "Installed package list does not exist"
-            return
-        end
-        pkg_all_list = [] 
-        pkg_list = pkg_hash.values
-        pkg_list.each do |p|
-            pkg_all_list.push([p.package_name, p.version, p.description])
-        end
-        return pkg_all_list.sort
-    end
-    
-    private
-    def get_build_dependency_arr(pkg_name, os, n)
-        pkg_hash = @pkg_hash_os[os]
-        pkg = pkg_hash[pkg_name]
-
-        if pkg.nil? then
-            @log.error "\"#{pkg_name}\" package does not exist in server. please check it"
-            return
-        end
-
-        # if package is already installed, skip tracing dependency
-        if check_installed_pkg(pkg_name) then
-            # compare version with installed package version
-            new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
-            compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
-            if compare_result == -1 or compare_result == 0 then return end
-        end
-
-        pkg.build_dep_list.each do |l|
-            @all_dep_list.push([n, l])
-            get_build_dependency_arr(l.package_name, os, n+1)
-        end
-    
-        return
-    end
-
-    private
-    def get_install_dependency_arr(pkg_name, os, force, n)
-
-        pkg_hash = @pkg_hash_os[os]
-        pkg = pkg_hash[pkg_name]
-
-        if pkg.nil? then
-            @log.error "\"#{pkg_name}\" package does not exist in server. please check it"
-            return
-        end
-    
-        # if package is already installed, skip tracing dependency
-        if check_installed_pkg(pkg_name) then
-            # compare version with installed package version
-            new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
-            compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
-            if not force then
-                if compare_result == -1 or compare_result == 0 then return end
-            end
-        end
-
-        pkg.install_dep_list.each do |l|
-            @all_dep_list.push([n, l])
-            get_install_dependency_arr(l.package_name, os, force, n+1)
-        end
-    
-        return 
-    end
-    
-    private
-    def get_all_reverse_install_dependency_arr(pkg_name, n)
-
-        s = "#{n}:#{pkg_name}"
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]                 
-        pkg_list = pkg_hash.values
-        pkg_list.each do |pkg|
-            pkg.install_dep_list.each do |l|
-                if l.package_name.eql? pkg_name then
-                    s = s + "::" + get_all_reverse_install_dependency_arr(pkg.package_name, n+1)
-                end
-            end
-        end
-
-        return s
-    end
-
-    private
-    def get_all_reverse_install_dependency_arr_remote(pkg_name, os, n)
-
-        s = "#{n}:#{pkg_name}"
-        pkg_hash = @pkg_hash_os[os]                 
-        pkg_list = pkg_hash.values
-        pkg_list.each do |pkg|
-            pkg.install_dep_list.each do |l|
-                if l.package_name.eql? pkg_name then
-                    s = s + "::" + get_all_reverse_install_dependency_arr_remote(pkg.package_name, os, n+1)
-                end
-            end
-        end
-
-        return s
-    end
-
-    private 
-    def get_pkg_from_list(pkg_name, os)
-
-        pkg_hash = @pkg_hash_os[os]
-        if pkg_hash.nil? then return nil end
-        pkg = pkg_hash[pkg_name]
-        
-        return pkg
-    end
-
-    private
-    def get_installed_pkg_from_list(pkg_name)
-
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
-        pkg = pkg_hash[pkg_name]
-        if pkg.nil? then return nil end
-
-        return pkg
-    end
-    
-    private
-    def install_pkg(pkg_name, os, force)
-
-        new_pkg_ver = ""
-        
-        # install remote server package file
-        if not check_remote_pkg(pkg_name, os) then
-            @log.error "\"#{pkg_name}\" package does not exist in remote server"
-            return false
-        end
-        path = get_attr_from_pkg(pkg_name, os, "path")
-        # type should be binary. type = "binary"
-        # below code should be changed
-        type = path.split('/')[-2]
-        new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
-            
-        # compare version with installed package versiona
-        compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
-        if not force then
-            case compare_result
-            when -1 then
-               @log.warn "\"#{pkg_name}\" package version is bigger then remote package version"
-               return true
-            when 0 then
-               @log.warn "\"#{pkg_name}\" package version is same with remote package version"
-               return true
-            end
-        end
-        
-        if check_installed_pkg(pkg_name) then
-            uninstall(pkg_name, false)
-        end 
-
-        # download file
-        # change download location temporary (back to the origin path after downloading)
-        loc_back = @location
-        uniq_name = Utils.create_uniq_name
-        tmppath = Utils::HOME + "/tmp/#{uniq_name}"
-        FileUtils.mkdir_p "#{tmppath}"
-        @location = tmppath
-        file_local_path = download(pkg_name, os, false)[0]
-        @location = loc_back        
-        if file_local_path.nil? then return false end
-    
-        # install package
-        ret = FileInstaller.install(pkg_name, file_local_path, type, @location)
-        FileUtils.rm_f(file_local_path)
-        FileUtils.remove_dir(tmppath, true)
-        return ret
-    end
-
-    private
-    def compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
-
-        if check_installed_pkg_list_file() then
-            create_installed_pkg_hash()
-            if check_installed_pkg(pkg_name) then
-                installed_pkg_ver = get_attr_from_installed_pkg(pkg_name, "version")
-                compare_result = Utils.compare_version(installed_pkg_ver, new_pkg_ver)
-                return compare_result
-            end
-        end
-
-        return 2
-    end
-
-    private
-    def remove_pkg_info(pkg_name)
-
-        pkg_hash = {}
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then
-            pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
-            if pkg_hash.include? pkg_name then
-                pkg_hash.delete(pkg_name)
-            end
-            @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
-        else return nil end
-        
-        @log.info "Removed information for \"#{pkg_name}\" package.. OK"
-        return pkg_hash
-    end
-
-    private
-    def add_pkg_info(pkg_name, os)
-
-        pkg_hash = {}
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then
-            pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]                
-            pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os)
-        else pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) end
-        @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
-
-        @log.info "Added information for \"#{pkg_name}\" package.. OK"
-        return pkg_hash
-    end
-
-    private
-    # add package manifest info
-    def add_local_pkg_info(pkg_name)
-        
-        config_path = File.join(@location, PACKAGE_INFO_DIR, "#{pkg_name}")
-        pkg = read_pkginfo_file(pkg_name, config_path)
-
-        if pkg.nil? then
-            @log.error "Failed to read pkginfo.manifest file"
-            return nil
-        end
-
-        pkg_hash = {} 
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then
-            pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]                
-            pkg_hash[pkg_name] = pkg
-        else pkg_hash[pkg_name] = pkg end
-        @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
-
-        @log.info "Added information for \"#{pkg_name}\" package.. OK"
-        return pkg_hash
-    end
-
-    private
-    # read package manifet info
-    def read_pkginfo_file(pkg_name, path)
-
-        file_path = File.join(path, "pkginfo.manifest")
-        pkg_hash = Parser.read_pkg_list(file_path)
-
-        if pkg_hash.nil? then
-            @log.error "Failed to read manifest file : #{file_path}"
-            return nil
-        end
-
-        @log.info "Added information for \"#{pkg_name}\" package.. OK"
-        return pkg_hash[pkg_name]
-    end
-
-    private
-    # from_server : if true, update from server
-    def create_remote_pkg_hash(from_server)
-
-        for os in SUPPORTED_OS
-            filename = PKG_LIST_FILE_PREFIX + os
-            file_url = @server_addr + "/" + filename
-            local_file_path = File.join(CONFIG_PATH, filename)
-            if from_server then 
-                if not FileDownLoader.download(file_url, CONFIG_PATH) then
-                    return false
-                end
-            end
-            local_file_path = File.join(CONFIG_PATH, filename)
-            if File.exist? local_file_path then
-                pkg_hash = Parser.read_pkg_list(local_file_path)
-                @pkg_hash_os[os] = pkg_hash
-            end
-        end
-
-        filename = "archive_pkg_list"
-        file_url = @server_addr + "/" + filename
-        if from_server then 
-            if not FileDownLoader.download(file_url, CONFIG_PATH) then
-                @log.warn "Server does not have \"#{filename}\" file. This error can be ignored."
-            end
-        end
-        local_file_path = File.join(CONFIG_PATH, filename)
-        if File.exist? local_file_path then
-            File.open(local_file_path, "r") do |f|
-                f.each_line do |l|
-                    @archive_pkg_list.push(l.strip)
-                end
-            end
-        end
-
-        return true
-    end
-    
-    private
-    # create installed package hash
-    def create_installed_pkg_hash()
-
-        config_path = File.join(@location, PACKAGE_INFO_DIR)
-        if not File.directory? config_path then return end
-
-        installed_pkg_hash_key = get_installed_pkg_list_file_path()
-        if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then return
-        else      
-            file_path = installed_pkg_hash_key
-            if not File.exist? file_path then
-                #raise RuntimeError, "#{file_path} file does not exist"
-                return
-            end
-            pkg_hash = Parser.read_pkg_list(file_path)
-            @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
-        end
-    end
-
-    private
-    # check to exist installed package list file
-    def check_installed_pkg_list_file()
-
-        if @location.nil? then raise RuntimeError, "#{@location} path does not exist" end
-        file_path = get_installed_pkg_list_file_path()
-        if File.exist? file_path then return true
-        else return false end
-    end
-
-    private
-    # get installed package list file path
-    def get_installed_pkg_list_file_path()
-
-        file_full_path = File.join(@location, PACKAGE_INFO_DIR, INSTALLED_PKG_LIST_FILE)        
-        return file_full_path
-    end
-
-    private
-    # write package hash to file
-    def write_pkg_hash_to_file(pkg_hash)
-
-        file_path = get_installed_pkg_list_file_path()
-        if pkg_hash.nil? then
-            pkg_hash = @installed_pkg_hash_loc[file_path]
-        end
-        if not pkg_hash.nil? then
-            config_path = File.join(@location, PACKAGE_INFO_DIR)
-            FileUtils.mkdir_p "#{config_path}"
-            if File.exist? file_path then File.delete(file_path) end
-            File.open(file_path, "a+") do |file|
-                file.puts "ORIGIN : #{@server_addr}"
-                file.puts "\n"
-                pkg_list = pkg_hash.values
-                pkg_list.each do |pkg|
-                    pkg.print_to_file(file)
-                    file.puts "\n"
-                end
-            end
-        end
-        @log.info "Write package informations to \"#{file_path}\".. OK"
-    end
-
-    private
-    def check_meta_pkg(pkg_name, os)
-        if not check_remote_pkg(pkg_name, os) then return false end
-
-        attr = get_attr_from_pkg(pkg_name, os, "attribute")
-        if attr.nil? or attr.empty? then return false end
-        if attr[0].strip.upcase.eql? "META" then return true
-        else return false end
-    end
+       # reverse : return reverse result
+       # force : install package force
+       def get_install_dependent_packages(pkg_name, os, reverse, force)
+
+               if not check_remote_pkg(pkg_name, os) then return nil end
+               if reverse.nil? then reverse = true end
+
+               @all_dep_list.clear
+               begin
+                       get_install_dependency_arr(pkg_name, os, force, 0)
+                       # in case of cross build dependency
+               rescue SystemStackError
+                       @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
+                       return nil
+               end
+
+               max = 0
+               @all_dep_list.each do |p|
+                       if p[0].to_i > max then
+                               max = p[0].to_i
+                       else next end
+               end
+
+               result = []
+               i = 0
+               while i <= max
+                       @all_dep_list.each do |p|
+                               if p[0].to_i.eql? i then
+                                       d = p[1]
+                                       remote_ver = get_attr_from_pkg(d.package_name, os, "version")
+                                       if not d.match? remote_ver then
+                                               @log.error "\"#{pkg_name}\" package needs \"#{d.package_name}\" #{d.comp} #{d.base_version}, but \"#{d.package_name}\" (#{remote_ver}) package is in server"
+                                               return nil
+                                       else result.push(d.package_name) end
+                               end
+                       end
+                       i = i + 1
+               end
+
+               @log.info "Get install dependent packages for \"#{pkg_name}\" package.. OK"
+               if reverse then return result.reverse.uniq.push(pkg_name)
+               else return result.uniq.insert(0, pkg_name) end
+       end
+
+       public
+       # get all reverse install dependent packages (considered reverse install priority for tracing uninstall)
+       def get_all_reverse_install_dependent_packages(pkg_name, reverse)
+
+               if not check_installed_pkg(pkg_name) then return nil end
+               if reverse.nil? then reverse = true end
+
+               begin
+                       res = get_all_reverse_install_dependency_arr(pkg_name, 0)
+               rescue SystemStackError
+                       @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
+                       return nil
+               end
+               res2 = res.split("::")
+               result = []
+               res2.each do |r|
+                       result.push(r.split(':')[1])
+               end
+
+               @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK"
+               if reverse then return result.reverse.uniq
+               else return result end
+       end
+
+       public
+       # get all reverse remote dependent packages (considered reverse install priority for tracing uninstall)
+       def get_all_reverse_install_dependent_packages_remote(pkg_name, os, reverse)
+               #if not check_remote_pkg(pkg_name, os) then return nil end
+               if reverse.nil? then reverse = true end
+
+               begin
+                       res = get_all_reverse_install_dependency_arr_remote(pkg_name, os, 0)
+               rescue SystemStackError
+                       @log.error "Failed to get dependency relation because #{pkg_name} package has cross install dependency."
+                       return nil
+               end
+               res2 = res.split("::")
+               result = []
+               res2.each do |r|
+                       result.push(r.split(':')[1])
+               end
+
+               @log.info "Get all reverse install dependent packages for #{pkg_name} package.. OK"
+               if reverse then return result.reverse
+               else return result end
+       end
+
+       public
+       # check package whether to exist in remote server
+       def check_remote_pkg(pkg_name, os)
+
+               pkg_hash = @pkg_hash_os[os]
+               if pkg_hash.nil? then return false end
+               pkg = pkg_hash[pkg_name]
+               if pkg.nil? then
+                       #@log.warn "There is no \"#{pkg_name}\" remote package information in list"
+                       return false
+               end
+
+               return true
+       end
+
+       public
+       # check package whether to exist in installed packages
+       def check_installed_pkg(pkg_name)
+
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
+               if pkg_hash.nil? then return false end
+               pkg = pkg_hash[pkg_name]
+
+               if pkg.nil? then return false end
+               return true
+       end
+
+       public
+       # get attribute from installed package
+       def get_attr_from_installed_pkg(pkg_name, attr)
+
+               if not check_installed_pkg(pkg_name) then return nil end
+               pkg = get_installed_pkg_from_list(pkg_name)
+
+               if pkg.nil? then return nil end
+
+               case attr
+               when "version" then return pkg.version
+               when "source" then return pkg.source
+               when "src_path" then return pkg.src_path
+               when "os" then return pkg.os
+               when "build_dep_list" then return pkg.build_dep_list
+               when "install_dep_list" then return pkg.install_dep_list
+               when "attribute" then return pkg.attribute
+               end
+       end
+
+       public
+       # get attribute from remote package
+       def get_attr_from_pkg(pkg_name, os, attr)
+
+               if not check_remote_pkg(pkg_name, os) then return nil end
+               pkg = get_pkg_from_list(pkg_name, os)
+
+               if pkg.nil? then return nil end
+
+               case attr
+               when "name" then return pkg.package_name
+               when "path" then return pkg.path
+               when "source" then return pkg.source
+               when "version" then return pkg.version
+               when "src_path" then return pkg.src_path
+               when "os" then return pkg.os
+               when "build_dep_list" then return pkg.build_dep_list
+               when "install_dep_list" then return pkg.install_dep_list
+               when "attribute" then return pkg.attribute
+               when "checksum" then return pkg.checksum
+               when "size" then return pkg.size
+
+               end
+       end
+
+       public
+       # show a package information
+       def show_pkg_info(pkg_name, os)
+               if not check_remote_pkg(pkg_name, os) then
+                       @log.error "\"#{pkg_name}\" package does not exist"
+                       return ""
+               end
+
+               pkg = get_pkg_from_list(pkg_name, os)
+               return pkg.to_s
+       end
+
+       public
+       # show all packages information
+       def show_pkg_list(os)
+               pkg_hash = @pkg_hash_os[os]
+               if pkg_hash.nil? then
+                       @log.error "\"#{os}\" package list does not exist"
+                       return ""
+               end
+
+               pkg_all_list = []
+               pkg_list = pkg_hash.values
+               pkg_list.each do |p|
+                       pkg_all_list.push([p.package_name, p.version, p.description])
+               end
+               return pkg_all_list.sort
+       end
+
+       public
+       # show installed package information
+       def show_installed_pkg_info(pkg_name)
+
+               if not check_installed_pkg(pkg_name) then
+                       @log.error "\"#{pkg_name}\" package does not exist"
+                       return ""
+               end
+
+               pkg = get_installed_pkg_from_list(pkg_name)
+               return pkg.to_s
+       end
+
+       public
+       # show all installed packages information
+       def show_installed_pkg_list()
+
+               file_path = get_installed_pkg_list_file_path()
+               pkg_hash = @installed_pkg_hash_loc[file_path]
+               if pkg_hash.nil? then
+                       @log.error "Installed package list does not exist"
+                       return nil
+               end
+               pkg_all_list = []
+               pkg_list = pkg_hash.values
+               pkg_list.each do |p|
+                       pkg_all_list.push([p.package_name, p.version, p.description])
+               end
+               return pkg_all_list.sort
+       end
+
+       private
+       def get_build_dependency_arr(pkg_name, os, n)
+               pkg_hash = @pkg_hash_os[os]
+               pkg = pkg_hash[pkg_name]
+
+               if pkg.nil? then
+                       @log.error "\"#{pkg_name}\" package does not exist in server. please check it"
+                       return
+               end
+
+               # if package is already installed, skip tracing dependency
+               if check_installed_pkg(pkg_name) then
+                       # compare version with installed package version
+                       new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
+                       compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+                       if compare_result == -1 or compare_result == 0 then return end
+               end
+
+               pkg.build_dep_list.each do |l|
+                       @all_dep_list.push([n, l])
+                       get_build_dependency_arr(l.package_name, os, n+1)
+               end
+
+               return
+       end
+
+       private
+       def get_install_dependency_arr(pkg_name, os, force, n)
+
+               pkg_hash = @pkg_hash_os[os]
+               pkg = pkg_hash[pkg_name]
+
+               if pkg.nil? then
+                       @log.error "\"#{pkg_name}\" package does not exist in server. please check it"
+                       return
+               end
+
+               # if package is already installed, skip tracing dependency
+               if check_installed_pkg(pkg_name) then
+                       # compare version with installed package version
+                       new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
+                       compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+                       if not force then
+                               if compare_result == -1 or compare_result == 0 then return end
+                       end
+               end
+
+               pkg.install_dep_list.each do |l|
+                       @all_dep_list.push([n, l])
+                       get_install_dependency_arr(l.package_name, os, force, n+1)
+               end
+
+               return
+       end
+
+       private
+       def get_all_reverse_install_dependency_arr(pkg_name, n)
+
+               s = "#{n}:#{pkg_name}"
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
+               pkg_list = pkg_hash.values
+               pkg_list.each do |pkg|
+                       pkg.install_dep_list.each do |l|
+                               if l.package_name.eql? pkg_name then
+                                       s = s + "::" + get_all_reverse_install_dependency_arr(pkg.package_name, n+1)
+                               end
+                       end
+               end
+
+               return s
+       end
+
+       private
+       def get_all_reverse_install_dependency_arr_remote(pkg_name, os, n)
+
+               s = "#{n}:#{pkg_name}"
+               pkg_hash = @pkg_hash_os[os]
+               pkg_list = pkg_hash.values
+               pkg_list.each do |pkg|
+                       pkg.install_dep_list.each do |l|
+                               if l.package_name.eql? pkg_name then
+                                       s = s + "::" + get_all_reverse_install_dependency_arr_remote(pkg.package_name, os, n+1)
+                               end
+                       end
+               end
+
+               return s
+       end
+
+       public
+       def get_pkg_from_list(pkg_name, os)
+
+               pkg_hash = @pkg_hash_os[os]
+               if pkg_hash.nil? then return nil end
+
+               pkg = pkg_hash[pkg_name]
+
+               return pkg
+       end
+
+       private
+       def get_installed_pkg_from_list(pkg_name)
+
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
+               pkg = pkg_hash[pkg_name]
+               if pkg.nil? then return nil end
+
+               return pkg
+       end
+
+       private
+       # install a package to @location after uninstalling and downloading
+       def install_pkg(pkg_name, os, force)
+
+               new_pkg_ver = ""
+
+               # install remote server package file
+               if not check_remote_pkg(pkg_name, os) then
+                       @log.error "\"#{pkg_name}\" package does not exist in remote server"
+                       return false
+               end
+               path = get_attr_from_pkg(pkg_name, os, "path")
+               # type should be binary. type = "binary"
+               # below code should be changed
+               type = path.split('/')[-2]
+               new_pkg_ver = get_attr_from_pkg(pkg_name, os, "version")
+               pkg_checksum = get_attr_from_pkg(pkg_name, os, "checksum")
+               pkg_size = get_attr_from_pkg(pkg_name, os, "size")
+               pkg_path = get_attr_from_pkg(pkg_name, os, "path")
+               filename = pkg_path.split('/')[-1]
+
+               # compare version with installed package versiona
+               compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+               if not force then
+                       case compare_result
+                       when -1 then
+                               @log.warn "Checked \"#{pkg_name}\" package version : it is bigger then remote package version"
+                               return true
+                       when 0 then
+                               @log.warn "Checked \"#{pkg_name}\" package version : it is same with remote package version"
+                               return true
+                       end
+               end
+
+               # if package is already installed, then uninstall it
+               if check_installed_pkg(pkg_name) then
+                       if not uninstall(pkg_name, false) then
+                               @log.error "Failed to uninstall \"#{pkg_name}\""
+                               return false
+                       end
+               end
+
+               # install package
+               cached_filepath = nil
+               if Utils.is_linux_like_os( Utils::HOST_OS ) then
+                       cached_filepath = get_cached_filepath(filename, pkg_checksum, pkg_size)
+               end
+               if not cached_filepath.nil? then
+                       @log.info "Cached #{pkg_name} package file.. OK"
+                       ret = FileInstaller.install(pkg_name, cached_filepath, type, @location, @log)
+               else
+                       filepath = download(pkg_name, os, false, @tmp_path)
+                       if filepath.nil? then
+                               return false
+                       end
+                       filepath = move_downloaded_pkg(filepath[0], @download_path)
+                       if filepath.nil? then
+                               return false
+                       end
+                       ret = FileInstaller.install(pkg_name, filepath, type, @location, @log)
+                       remove_downloaded_pkgs(pkg_name, os)
+               end
+               return ret
+       end
+
+       private
+       def compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+
+               if check_installed_pkg_list_file() then
+                       read_installed_pkg_list()
+                       if check_installed_pkg(pkg_name) then
+                               installed_pkg_ver = get_attr_from_installed_pkg(pkg_name, "version")
+                               compare_result = Utils.compare_version(installed_pkg_ver, new_pkg_ver)
+                               return compare_result
+                       end
+               end
+
+               return 2
+       end
+
+       private
+       def remove_pkg_info(pkg_name)
+
+               pkg_hash = {}
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then
+                       pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
+                       if pkg_hash.include? pkg_name then
+                               pkg_hash.delete(pkg_name)
+                       end
+                       @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
+               else return nil end
+
+               @log.info "Removed information for \"#{pkg_name}\" package.. OK"
+               return pkg_hash
+       end
+
+       private
+       def add_pkg_info(pkg_name, os)
+
+               pkg_hash = {}
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then
+                       pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
+                       pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os)
+               else pkg_hash[pkg_name] = get_pkg_from_list(pkg_name, os) end
+               @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
+
+               #@log.info "Added information for \"#{pkg_name}\" package.. OK"
+               return pkg_hash
+       end
+
+       private
+       # add package manifest info
+       def add_local_pkg_info(pkg_name)
+
+               config_path = File.join(@location, PACKAGE_INFO_DIR, "#{pkg_name}")
+               pkg = read_pkginfo_file(pkg_name, config_path)
+
+               if pkg.nil? then
+                       @log.error "Failed to read pkginfo.manifest file"
+                       return nil
+               end
+
+               pkg_hash = {}
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then
+                       pkg_hash = @installed_pkg_hash_loc[installed_pkg_hash_key]
+                       pkg_hash[pkg_name] = pkg
+               else pkg_hash[pkg_name] = pkg end
+               @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
+
+               #@log.info "Added information for \"#{pkg_name}\" package.. OK"
+               return pkg_hash
+       end
+
+       private
+       # read package manifet info
+       def read_pkginfo_file(pkg_name, path)
+
+               file_path = File.join(path, "pkginfo.manifest")
+               begin
+                       pkg = Parser.read_single_pkginfo_from file_path
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+                       return nil
+               end
+
+               if pkg.nil? then
+                       @log.error "Failed to read manifest file : #{file_path}"
+                       return nil
+               end
+
+               @log.info "Read information for \"#{pkg_name}\" package.. OK"
+               return pkg
+       end
+
+       # get the lastest snapshot
+       # from_server : if true, update from server
+       def get_lastest_snapshot(from_server)
+               ssinfo_file = "snapshot.info"
+               file_url = File.join(@server_addr, ssinfo_file)
+               if from_server then
+                       if not FileDownLoader.download(file_url, @config_dist_path, @log) then
+                               @log.warn "Server does not have \"#{ssinfo_file}\" file. This error can be ignored."
+                       end
+               else
+                       if File.exist? file_url then FileUtils.cp(file_url, @config_dist_path)
+                       else @log.warn "Server does not have \"#{ssinfo_file}\" file. This error can be ignored." end
+               end
+
+               file_path = File.join(@config_dist_path, ssinfo_file)
+               if not File.exist? file_path then return nil end
+
+               contents = File.open(file_path, "r").read
+
+               _list = contents.split("\n\n")
+               if _list.nil? or _list == "" or _list.empty? then return nil end
+               list = _list[-1].split("\n")
+               if list.nil? or list == "" or list.empty? then return nil end
+               _path = list[-1].split(":")
+               if _path.nil? or _path == ""  or _path.length != 2 then return nil end
+               path = _path[1].strip
+               if path == nil or path == "" then return nil end
+
+               return path
+       end
+
+       def get_pkglist_path()
+               return File.join(@config_dist_path, @snapshot_path)
+       end
+
+       # if url includes snapshot infomation, retuen true
+       def is_snapshot_url(addr = nil)
+               if addr.nil? then addr = @server_addr end
+               addr_arr = addr.split('/')
+               if addr_arr[-2].eql? "snapshots" then
+                       return true
+               else
+                       return false
+               end
+       end
+
+       def split_addr_and_snapshot(addr = nil)
+               if addr.nil? then addr = @server_addr end
+               addr_arr = addr.split('/')
+               if addr_arr[-2].eql? "snapshots" then
+                       return addr_arr[0..-3].join("/"), addr_arr[-2..-1].join("/")
+               else
+                       return nil
+               end
+       end
+
+       def is_snapshot_exist(ss_path = nil)
+               if ss_path.nil? then ss_path = @snapshot_path
+               elsif ss_path == "" then return false end
+
+               local_snapshot_path = File.join(@config_dist_path, ss_path)
+               if File.directory? local_snapshot_path then return true
+               else return false end
+       end
+
+       def read_remote_pkg_list(list_path)
+               @support_os_list.each do |os|
+                       filename = PKG_LIST_FILE_PREFIX + os
+                       local_file_path = File.join(list_path, filename)
+                       if File.exist? local_file_path then
+                               begin
+                                       pkg_hash = Parser.read_repo_pkg_list_from local_file_path
+                                       @pkg_hash_os[os] = pkg_hash
+                                       @log.info "Get package information for #{os}.. OK"
+                               rescue => e
+                                       @log.error( e.message, Log::LV_USER)
+                                       @pkg_hash_os[os] = {}
+                               end
+                       else
+                               @log.warn "Failed to read pkg_list_#{os} file"
+                               @pkg_hash_os[os] = {}
+                       end
+               end
+       end
+
+       def read_supported_os_list(list_path)
+               local_file_path = File.join(list_path, OS_INFO_FILE)
+               if File.exist? local_file_path then
+                       File.open(local_file_path, "r") do |f|
+                               f.each_line do |l|
+                                       os = l.strip
+                                       if @support_os_list.index(os).nil? then @support_os_list.push(os) end
+                               end
+                       end
+                       @log.info "Get supported os infomation.. OK"
+               else
+                       @log.warn "Failed to get supported os infomation"
+               end
+       end
+
+       def download_os_list(from_server, dist = nil)
+               if dist.nil? then dist = get_pkglist_path end
+               file_url = File.join(@server_addr, OS_INFO_FILE)
+               if from_server then
+                       if not FileDownLoader.download(file_url, dist, @log) then return false end
+               else
+                       if File.exist? file_url then FileUtils.cp(file_url, dist)
+                       else return false end
+               end
+
+               return true
+       end
+
+       def read_archive_pkg_list(list_path)
+               local_file_path = File.join(list_path, ARCHIVE_PKG_LIST_FILE)
+               if File.exist? local_file_path then
+                       File.open(local_file_path, "r") do |f|
+                               f.each_line do |l|
+                                       pkg = l.strip
+                                       if @archive_pkg_list.index(pkg).nil? then @archive_pkg_list.push(pkg) end
+                               end
+                       end
+                       @log.info "Get archive package infomation.. OK"
+               else
+                       @log.warn "Failed to get archive package infomation"
+               end
+       end
+
+       def download_archive_pkg_list(from_server, dist = nil)
+               if dist.nil? then dist = get_pkglist_path end
+               file_url = File.join(@server_addr, @snapshot_path, ARCHIVE_PKG_LIST_FILE)
+               if from_server then
+                       if not FileDownLoader.download(file_url, dist, @log) then return false end
+               else
+                       if File.exist? file_url then FileUtils.cp(file_url, dist)
+                       else return false end
+               end
+
+               return true
+       end
+
+       def download_pkg_list(from_server, dist = nil)
+               if dist.nil? then dist = get_pkglist_path end
+               @support_os_list.each do |os|
+                       filename = PKG_LIST_FILE_PREFIX + os
+                       file_url = File.join(@server_addr, @snapshot_path, filename)
+                       if from_server then
+                               if not FileDownLoader.download(file_url, dist, @log) then return false end
+                       else
+                               if File.exist? file_url then FileUtils.cp(file_url, dist)
+                               else return false end
+                       end
+               end
+
+               return true
+       end
+
+       private
+       # create installed package hash
+       def read_installed_pkg_list()
+
+               config_path = File.join(@location, PACKAGE_INFO_DIR)
+               if not File.directory? config_path then return end
+
+               installed_pkg_hash_key = get_installed_pkg_list_file_path()
+               if @installed_pkg_hash_loc.has_key? installed_pkg_hash_key then return
+               else
+                       file_path = installed_pkg_hash_key
+                       if not File.exist? file_path then
+                               #raise RuntimeError, "#{file_path} file does not exist"
+                               return
+                       end
+                       begin
+                               pkg_hash = Parser.read_repo_pkg_list_from file_path
+                       rescue => e
+                               @log.error( e.message, Log::LV_USER)
+                               return
+                       end
+                       @installed_pkg_hash_loc[installed_pkg_hash_key] = pkg_hash
+               end
+       end
+
+       private
+       # check to exist installed package list file
+       def check_installed_pkg_list_file()
+
+               if @location.nil? then raise RuntimeError, "#{@location} path does not exist" end
+               file_path = get_installed_pkg_list_file_path()
+               if File.exist? file_path then return true
+               else return false end
+       end
+
+       private
+       # get installed package list file path
+       def get_installed_pkg_list_file_path()
+
+               file_full_path = File.join(@location, PACKAGE_INFO_DIR, INSTALLED_PKG_LIST_FILE)
+               return file_full_path
+       end
+
+       private
+       # write package hash to file
+       def write_pkg_hash_to_file(pkg_hash)
+
+               file_path = get_installed_pkg_list_file_path()
+               if pkg_hash.nil? then
+                       pkg_hash = @installed_pkg_hash_loc[file_path]
+               end
+               if not pkg_hash.nil? then
+                       config_path = File.join(@location, PACKAGE_INFO_DIR)
+                       if not File.exist? config_path then FileUtils.mkdir_p "#{config_path}" end
+                       if File.exist? file_path then File.delete(file_path) end
+                       File.open(file_path, "a+") do |file|
+                               pkg_list = pkg_hash.values
+                               pkg_list.each do |pkg|
+                                       pkg.print_to_file(file)
+                                       file.puts "\n"
+                               end
+                       end
+               end
+               @log.info "Write package informations to \"#{file_path}\".. OK"
+       end
+
+       private
+       def check_meta_pkg(pkg_name, os)
+               if not check_remote_pkg(pkg_name, os) then return false end
+
+               attr = get_attr_from_pkg(pkg_name, os, "attribute")
+               if attr.nil? or attr.empty? then return false end
+               if attr[0].strip.upcase.eql? "META" then return true
+               else return false end
+       end
 end
index ae12c36055a3e9c56170922750a2cde0a9fa1708..fff8924eb614b9825c0df00406e723752322f653 100644 (file)
@@ -1,5 +1,5 @@
 =begin
+
  clientOptParser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
@@ -30,194 +30,177 @@ require 'optparse'
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "utils"
 
-def set_default( options ) 
+def set_default( options )
        if options[:t].nil? then options[:t] = false end
        if options[:f].nil? then options[:f] = false end
        if options[:v].nil? then options[:v] = false end
 end
 
 def option_error_check( options )
-       $log.info "option error check"
 
        case options[:cmd]
 
-    when "update" then
-
-    when "clean" then
-
-    when "upgrade" then
+       when "update" then
 
-    when "check-upgrade" then
+       when "clean" then
 
-    when "download" then
-        if options[:pkg].nil? or options[:pkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli download -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>] [-t]"
-        end
+       when "upgrade" then
 
-    when "upload" then
-        if options[:alias].nil? or options[:alias].empty? or\
-                options[:id].nil? or options[:id].empty? or \
-                options[:srcpkg].nil? or options[:srcpkg].empty? then 
-                   raise ArgumentError, "Usage: pkg-cli upload -a <ssh_alias> -i <id> -s <source_package_path_list> [-b <binary_package_path_list>]"
-        end
+       when "check-upgrade" then
 
-    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>]"
-        end
+       when "download" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       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 
-                   raise ArgumentError, "Usage: pkg-cli install -p <pkg_name> [-o <os>] [-l <location>] [-u <package server url>] [-t] [-f]"
-        end
+       when "install" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       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 
-                   raise ArgumentError, "Usage: pkg-cli install-lpkg -p <pkg_file> [-l <location>] [-f]"
-        end
+       when "install-file" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       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 
-                   raise ArgumentError, "Usage: pkg-cli uninstall -p <pkg_name> [-l <location>] [-t]"
-        end
+       when "uninstall" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       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
-                   raise ArgumentError, "Usage: pkg-cli show-rpkg -p <pkg_name> [-o <os>] [-u <package server url>]"
-        end
+       when "show-rpkg" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       raise ArgumentError, "Usage: pkg-cli show-rpkg -P <package name> [-o <os>] [-u <package server url>]"
+               end
 
-    when "list-rpkg" then
+       when "list-rpkg" then
 
-    when "show-lpkg" then
-        if options[:pkg].nil? or options[:pkg].empty? then
-                   raise ArgumentError, "Usage: pkg-cli show-lpkg -p <pkg_name> [-l <location>]"
-        end
+       when "show-lpkg" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       raise ArgumentError, "Usage: pkg-cli show-lpkg -P <package name> [-l <location>]"
+               end
 
-    when "list-lpkg" then
+       when "list-lpkg" then
 
-    when "build-dep" then
-        if options[:pkg].nil? or options[:pkg].empty? then
-                   raise ArgumentError, "Usage: pkg-cli build-dep -p <pkg_name> [-o <os>]"
-        end
+       when "build-dep" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       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
-                   raise ArgumentError, "Usage: pkg-cli install-dep -p <pkg_name> [-o <os>]"
-        end
+       when "install-dep" then
+               if options[:pkg].nil? or options[:pkg].empty? then
+                       raise ArgumentError, "Usage: pkg-cli install-dep -P <package name> [-o <os>]"
+               end
 
        else
-               raise ArgumentError, "input option incorrect : #{options[:cmd]}"
+               raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
        end
 end
 
-def option_parse 
-    options = {}
-    optparse = OptionParser.new do|opts|
-        # Set a banner, displayed at the top
-        # of the help screen.
-        opts.banner = "Usage: pkg-cli {update|clean|download|source|install|uninstall|upgrade|rpkg-show|rpkg-list|lpkg-show|lpkg-list|build-dep|install-dep|help} ..." + "\n" \
-        + "\t" + "pkg-cli update [-u <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" \
-        + "\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 list-rpkg [-o <os>] [-u <package server url>]" + "\n" \
-        + "\t" + "pkg-cli show-lpkg -p <pkg_name> [-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"  \
-
-        opts.on( '-p', '--pkg <pkg_name or pkg_file>', 'package name or package file name' ) do |name|
-            options[:pkg] = name 
-        end
-        
-               opts.on( '-o', '--os <operating system>', 'target operating system' ) do |os|
-            options[:os] = os
-        end
-               
-               opts.on( '-u', '--url <server_address>', 'package server url' ) do|url|
-            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
-        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
-            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
-            options[:f] = true
-        end
-               
-               opts.on( '-h', '--help', 'display this information' ) do
-            puts opts
+def option_parse
+       options = {}
+       banner = "Requiest service to package-server and control packages service command-line tool." + "\n" \
+               + "\n" + "Usage: pkg-cli <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 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 show-lpkg -P <package name> [-l <location>]" + "\n"  \
+               + "\t" + "pkg-cli list-lpkg [-l <location>]" + "\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 <package name/file>', 'package name or package file name' ) do |name|
+                       options[:pkg] = name
+               end
+
+               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
+
+               opts.on( '-u', '--url <server url>', 'package server url: http://127.0.0.1/dibs/unstable' ) do |url|
+                       options[:url] = url
+               end
+
+               opts.on( '-l', '--loc <location>', 'install/download location' ) do |loc|
+                       options[:loc] = loc
+               end
+
+               opts.on( '--trace', 'enable trace dependent packages' ) do
+                       options[:t] = true
+               end
+
+               opts.on( '--force', 'enable force' ) do
+                       options[:f] = true
+               end
+
+               opts.on( '-h', '--help', 'display help' ) do
+                       puts opts
                        exit
-        end
-               
-    end
-    
-       $log.info "option parsing start" 
-    $log.info "option is : " + ARGV * "," 
-
-    cmd = ARGV[0] 
-    if cmd.eql? "update" or cmd.eql? "download" or \
-            cmd.eql? "install" or cmd.eql? "show-rpkg" or \
-            cmd.eql? "list-rpkg" or cmd.eql? "source" or \
-            cmd.eql? "uninstall" or cmd.eql? "show-lpkg" or \
-            cmd.eql? "list-lpkg" or cmd.eql? "upload" or \
-            cmd.eql? "install-file" or cmd.eql? "clean" or \
-            cmd.eql? "upgrade" or cmd.eql? "check-upgrade" or \
-            cmd.eql? "build-dep" or cmd.eql? "install-dep" or \
-            cmd =~ /(help)|(-h)|(--help)/  then
-        if cmd.eql? "help" then ARGV[0] = "-h" end
-        options[:cmd] = ARGV[0]
-    else
-        raise ArgumentError, "first paramter must be {update|clean|download|upload|source|install|install-file|uninstall|upgrade|check-upgrade|show-rpkg|list-rpkg|show-lpkg|list-lpkg|build-dep|install-dep|help} : your input is #{ARGV[0]}"
-    end
-
-    optparse.parse!
-   
-       $log.info "option parsing end" 
+               end
+
+               opts.on( '-v', '--version', 'display version' ) do
+                       puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
+                       exit
+               end
+       end
+
+       cmd = ARGV[0]
+       if cmd.eql? "update" or cmd.eql? "download" or
+               cmd.eql? "install" or cmd.eql? "show-rpkg" or
+               cmd.eql? "list-rpkg" or
+               cmd.eql? "uninstall" or cmd.eql? "show-lpkg" or
+               cmd.eql? "list-lpkg" or
+               cmd.eql? "install-file" or cmd.eql? "clean" or
+               cmd.eql? "upgrade" or cmd.eql? "check-upgrade" or
+               cmd.eql? "build-dep" or cmd.eql? "install-dep" or
+               cmd =~ /(-v)|(--version)/  or
+               cmd =~ /(help)|(-h)|(--help)/  then
+
+               if cmd.eql? "help" then
+                       V[0] = "-h"
+               end
+               options[:cmd] = ARGV[0]
+       else
+               raise ArgumentError, "Usage: pkg-cli <SUBCOMMAND> [OPTS] or pkg-cli -h"
+       end
+
+       optparse.parse!
 
        set_default options
 
-       # option error check 
+       # option error check
        option_error_check options
 
-    return options
-end 
+       return options
+end
 
index 09f8da108da7c0f8ef6ae8ad781178a9162f91de..5aa613b129fb992961d473044546ec4d328cb014 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- distribution.rb 
+
+ distribution.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -29,75 +29,88 @@ Contributors:
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "parser"
+require "installer"
 
-class Distribution 
-       attr_accessor :name, :location, :server_url
+class Distribution
+       attr_accessor :name, :location, :server_url, :lock_file_path, :last_sync_changes
 
-    # constant
-    SUPPORTED_OS = ["linux", "windows", "darwin"]
-    PKG_LIST_FILE_PREFIX = "pkg_list_" 
-       ARCHIVE_PKG_LIST = "archive_pkg_list"
+       # constant
+       PKG_LIST_FILE_PREFIX = "pkg_list_"
+       ARCHIVE_PKG_FILE = "archive_pkg_list"
+       OS_INFO_FILE = "os_info"
+       SNAPSHOT_INFO_FILE = "snapshot.info"
+       LOCK_FILE = ".lock_file"
+       SYNC_LOCK_FILE = ".sync_lock_file"
 
-       def initialize (name, location, server_url, log)
+       def initialize( name, location, server_url, pkg_server )
 
                @name = name
                @location = location
-               @pkg_hash_os = {}
-               @log = log
                @server_url = server_url
+               @log = pkg_server.log
+               @integrity = pkg_server.integrity
+               @lock_file_path = "#{location}/#{LOCK_FILE}"
+               @sync_lock_file_path = "#{location}/#{SYNC_LOCK_FILE}"
+               @pkg_hash_os = {}
+               @archive_pkg_list = []
+               @snapshot_hash = []
+               @support_os_list = []
+               @last_sync_changes = ""
+
                @log.info "Distribution class[#{name}] initialize "
 
-        for os in SUPPORTED_OS 
-                       if @location.empty? or ( not File.exist? "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" ) then
-                               @pkg_hash_os[os] = {}
-                       else 
-                               @pkg_hash_os[os] = Parser.read_pkg_list( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" )
-                       end
-               end
+               initialize_pkg_list()
        end
 
-       def register (file_path, pkg)
-               @log.info "Distribution class's register"
+       def register (file_path, pkg, internal_flag)
                if pkg.nil? then
                        raise RuntimeError, "package file does not contain pkginfo.manifest: [#{file_path}]"
                end
 
+               if not @pkg_hash_os.has_key?(pkg.os) then
+                       raise RuntimeError, "package server does not support package's os : [#{pkg.os}]"
+               end
+
                exist_pkg = @pkg_hash_os[pkg.os][pkg.package_name]
-          
+
                # version check and if existing version is higher then upload version?
-               if not exist_pkg.nil? 
-                       if not ( Utils.compare_version( exist_pkg.version, pkg.version ).eql? 1 ) then
-                               raise RuntimeError, "existing package's version is higher than register package"
+               if (not exist_pkg.nil?) and (not internal_flag) then
+                       if Utils.compare_version( exist_pkg.version, pkg.version ) != 1 then
+                               raise RuntimeError, "existing package's version is higher then register package : [#{pkg.package_name}] in [#{pkg.os}]"
                        end
                end
 
                # modified pkg class
-               pkg.origin = "local" 
-        pkg.source = ""
+               pkg.origin = "local"
+               pkg.source = ""
                pkg.path = "/binary/" + File.basename( file_path )
-               # TODO: windows and mac : sha256sum
-               if Utils::HOST_OS.eql? "linux" then
-                       pkg.checksum = `sha256sum #{file_path}`.split(" ")[0]
-               end 
-               pkg.size = `du -b #{file_path}`.split[0].strip
+               if pkg.checksum.empty? then
+                       # TODO: windows and mac : sha256sum
+                       if Utils.is_unix_like_os( Utils::HOST_OS ) then
+                               pkg.checksum = `sha256sum #{file_path}`.split(" ")[0]
+                       end
+               end
+
+               if pkg.size.empty? then
+                       pkg.size = `du -b #{file_path}`.split[0].strip
+               end
+
+               @pkg_hash_os[pkg.os][pkg.package_name] = pkg
 
-               @pkg_hash_os[pkg.os][pkg.package_name] = pkg 
-               
                return pkg
        end
 
        def register_for_test (file_path, pkg)
-               @log.info "Distribution class's register for test"
                if pkg.nil? then
                        raise RuntimeError, "package file does not contain pkginfo.manifest: [#{file_path}]"
                end
 
                # modified pkg class
-               pkg.origin = "local" 
-        pkg.source = ""
+               pkg.origin = "local"
+               pkg.source = ""
                pkg.path = "/temp/" + File.basename( file_path )
                # TODO: windows and mac : sha256sum
-               if Utils::HOST_OS.eql? "linux" then
+               if Utils.is_unix_like_os( Utils::HOST_OS ) then
                        pkg.checksum = `sha256sum #{file_path}`.split(" ")[0]
                end
                pkg.size = `du -b #{file_path}`.split[0].strip
@@ -105,393 +118,837 @@ class Distribution
                return pkg
        end
 
-       def generate_snapshot (name, base_snapshot, append_pkg_list)
-               @log.info "Distribution class's generate snapshot"
+       def register_archive_pkg( archive_pkg )
+               if not @archive_pkg_list.include? archive_pkg then
+                       @archive_pkg_list.push archive_pkg
+               else
+                       @log.error("archive package already exist : [#{archive_pkg}]", Log::LV_USER)
+               end
+       end
+
+       def generate_snapshot(name, base_snapshot, from_cmd, change_log_string)
                # if name is nil or empty then create uniq name
                if name.nil? or name.empty? then
                        name = Utils.create_uniq_name
                end
 
-               # check base snapshot exist 
-               if File.exist? "#{@location}/snapshots/#{name}" then 
+               # check base snapshot exist
+               if File.exist? "#{@location}/snapshots/#{name}" then
                        raise "Snapshot is already exist: #{name}"
                end
 
-               if base_snapshot.nil? then base_snapshot = "" else base_snapshot.strip! end
-               if append_pkg_list.nil? then append_pkg_list = [] end 
+               FileUtils.mkdir "#{@location}/snapshots/#{name}"
+               FileUtils.mkdir "#{@location}/changes" if not File.exists? "#{@location}/changes"
+               File.open( "#{@location}/changes/#{name}.log","w") { |f| f.puts change_log_string }
+
+               # base_snapshot_path
+               if base_snapshot.empty? then
+                       snapshot_path = @location
+               else
+                       snapshot_path = "#{@location}/snapshots/#{base_snapshot.strip}"
+               end
 
-               if base_snapshot.empty? and append_pkg_list.empty? then 
-                       FileUtils.mkdir "#{@location}/snapshots/#{name}"
+               # copy package list
+               @support_os_list.each do |os|
+                       FileUtils.copy_file( "#{snapshot_path}/#{PKG_LIST_FILE_PREFIX}#{os}",
+                                                               "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{os}" )
+               end
 
-               for os in SUPPORTED_OS 
-                               FileUtils.copy( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", 
-                                                          "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{os}" )
-                       end 
+               # copy archive package list
+               FileUtils.copy_file( "#{snapshot_path}/#{ARCHIVE_PKG_FILE}",
+                                                       "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_FILE}" )
 
-                       # copy archive package list
-                       begin 
-                               FileUtils.copy( "#{@location}/#{ARCHIVE_PKG_LIST}", "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_LIST}" )
-                       rescue => e
-                               @log.warn "ARCHIVE_PKG_LIST not exist"  
-                       end
+               # copy os info file
+               FileUtils.copy_file( "#{snapshot_path}/#{OS_INFO_FILE}",
+                                                       "#{@location}/snapshots/#{name}/#{OS_INFO_FILE}" )
 
+               # generate temp file
+               tmp_file_name = ""
+               while ( tmp_file_name.empty? )
+                       tmp_file_name = @location + "/temp/." + Utils.create_uniq_name
 
-                       @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER)
-               # base_snapshot is exist 
-               elsif not ( base_snapshot.empty? ) then
-                       FileUtils.mkdir "#{@location}/snapshots/#{name}"
-                       
-               for os in SUPPORTED_OS 
-                               # check base snapshot exist 
-                               if (not File.exist? "#{@location}/snapshots/#{base_snapshot}/#{PKG_LIST_FILE_PREFIX}#{os}") then
-                                       raise RuntimeError, "Can't find base snapshot [#{base_snapshot}]"
-                               end 
-                               
-                               base_pkg_list = Parser.read_pkg_list( "#{@location}/snapshots/#{base_snapshot}/#{PKG_LIST_FILE_PREFIX}#{os}" )
-                               snapshot_generate2( name, os, base_pkg_list, append_pkg_list )
+                       if File.exist? tmp_file_name then
+                               tmp_file_name = ""
                        end
-               
-                       # copy archive package list
-                       begin 
-                               FileUtils.copy( "#{@location}/#{ARCHIVE_PKG_LIST}", "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_LIST}" )
-                       rescue => e
-                               @log.warn "ARCHIVE_PKG_LIST not exist"  
+               end
+
+               FileUtils.copy_file( "#{@location}/#{SNAPSHOT_INFO_FILE}", tmp_file_name )
+               File.open( tmp_file_name, "a" ) do |f|
+                       f.puts "name : #{name}"
+                       f.puts "time : #{Time.now.strftime("%Y%m%d%H%M%S")}"
+                       if from_cmd then
+                               f.puts "type : manual"
+                       else
+                               f.puts "type : auto"
                        end
+                       f.puts "path : /snapshots/#{name}"
+                       f.puts
+               end
+               FileUtils.mv( tmp_file_name, "#{@location}/#{SNAPSHOT_INFO_FILE}", :force => true )
+
+               # snapshot is generated
+               @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER)
+               return name
+       end
 
-                       @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER)
-               # base_snapshot is empty
-               else 
-                       FileUtils.mkdir "#{@location}/snapshots/#{name}" 
+       def sync(force, snapshot = "")
+               pkg_list_update_flag = false
+               archive_update_flag = false
+               distribution_update_flag = false
+               changes = []
+               
+               # lock
+               sync_lock_file = Utils.file_lock(@sync_lock_file_path)
 
-               for os in SUPPORTED_OS  
-                               base_pkg_list = Parser.read_pkg_list( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" )
-                               snapshot_generate2( name, os, base_pkg_list, append_pkg_list )
-                       end 
+               # reload pkg list from newest pkg list file
+               reload_distribution_information()
 
-                       # copy archive package list
-                       begin 
-                               FileUtils.copy( "#{@location}/#{ARCHIVE_PKG_LIST}", "#{@location}/snapshots/#{name}/#{ARCHIVE_PKG_LIST}" )
-                       rescue => e
-                               @log.warn "ARCHIVE_PKG_LIST not exist"  
-                       end
+               # check distribution's server_url
+               if @server_url.empty? then
+                       @log.error("This distribution has not remote server")
+                       Utils.file_unlock(sync_lock_file)
+                       raise RuntimeError, "remote server address empty"
+               end
 
-                       @log.output( "snapshot is generated : #{@location}/snapshots/#{name}", Log::LV_USER)
+               # generate client class
+               if snapshot.nil? or snapshot.empty? then
+                       server_url = @server_url
+               else
+                       server_url = "#{@server_url}/snapshots/#{snapshot}"
                end
-       end  
+               client = Client.new( server_url, "#{@location}/binary", @log )
 
-       def snapshot_generate2( name, os, pkg_list, append_pkg_list )
-               @log.info "snapshot_generate2: input append_pkg_list #{append_pkg_list}"
-               append_pkg_list.each do |pkg| 
-                       # os check
-                       if pkg.os.eql? os.strip then pkg_list[pkg.package_name] = pkg end
+               # parents package server check
+               if client.pkg_hash_os.keys.empty? then
+                       @log.error("Sync process stopped by error.")
+                       @log.error("Parents package server does not have [[os_info]] file.")
+               
+                       Utils.file_unlock(sync_lock_file)
+                       raise RuntimeError, "Parents package server does not have [[os_info]] file."
                end
-       
-               File.open( "#{@location}/snapshots/#{name}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f|
-                       pkg_list.each_value do |pkg|
-                               pkg.print_to_file(f)
-                               f.puts 
+
+               # update os list
+               add_os_list = client.support_os_list - @support_os_list
+               add_os_list.each do |os|
+                       add_os(os)
+                       changes.push "Add OS #{os}"
+                       pkg_list_update_flag = true
+               end
+
+               if force then
+                       remove_os_list = @support_os_list - client.support_os_list
+                       remove_os_list.each do |os|
+                               remove_os(os)
+                               changes.push "Remove OS #{os}"
+                               pkg_list_update_flag = true
                        end
-               end     
-       end
+               end
+               update_pkg_list = []
 
-       def sync( force, os ) 
+               @support_os_list.each do |os|
+                       # error check
+                       if client.pkg_hash_os[os].nil? then
+                               @log.error("os[[#{os}]] is removed in parents package server", Log::LV_USER)
+                               next
+                       end
 
-               # check distribution's server_url
-               if @server_url.empty? then 
-                       @log.error( "This distribution has not remote server"  , Log::LV_USER)
-                       return
+                       server_pkg_name_list = client.pkg_hash_os[os].keys
+                       local_pkg_name_list = @pkg_hash_os[os].keys
+                       full_pkg_name_list = server_pkg_name_list + local_pkg_name_list
+                       full_pkg_name_list.uniq!
+
+                       full_pkg_name_list.each do |pkg_name|
+                               ret = sync_package( pkg_name, client, os, force )
+                               if not ret.nil? then
+                                       update_pkg_list.push(ret)
+                                       pkg_list_update_flag = true
+                               end
+                       end
                end
 
-               # generate client class
-               client_bin = Client.new( @server_url, "#{@location}/binary", @log )
-               client_bin.update
-               client_src = Client.new( @server_url, "#{@location}/source", @log )
-               client_src.update
-           
-               source_pkg_path_list = []
-               dep_pkg_path_list = []
-
-               # error check 
-               if client_bin.pkg_hash_os[os].nil? then 
-                       raise "Package list can't generated. url is #{@server_url}. os is #{os}"
-               end 
-
-               # check existing source package list 
-               @pkg_hash_os[os].each_value do |pkg|
-                       if not source_pkg_path_list.include? pkg.src_path then 
-                               source_pkg_path_list.push pkg.src_path
-                       end
-               end 
-
-               full_pkg_list = client_bin.pkg_hash_os[os].merge(@pkg_hash_os[os])
-
-               full_pkg_list.each_key do |pkg_name|
-                       server_pkg = client_bin.pkg_hash_os[os][pkg_name]
-                       local_pkg = @pkg_hash_os[os][pkg_name] 
-
-                       # if server and local has package
-                       if ( not server_pkg.nil? ) and ( not local_pkg.nil? ) then
-                               # if server version is not updated then skip
-                               if not ( Utils.compare_version( local_pkg.version, server_pkg.version ).eql? 1 ) then 
-                                       @log.info "existing packages version equal or higher then server's version so package[#{pkg_name}] skip"
-                                       @log.info "server package version: [#{server_pkg.version}]"
-                                       @log.info "local package version: [#{local_pkg.version}]" 
-                                       
-                                       next
-                               end 
+               # sync archive package
+               update_archive_list = sync_archive_pkg()
 
-                               # if server version is not updated then skip
-                               # if server's pakcage is local package and mode is not force then local package will be upaded 
-                               if ( local_pkg.origin.eql? "local" ) and ( not force ) then
-                                       @log.info "package [#{pkg_name}] is local package. so skip update"
-                                       
-                                       next
-                               end 
-
-                               # package update
-                               @log.info "update package from server: [#{pkg_name}]"
-                               file_path_list = client_bin.download( pkg_name, os, false )
-                               
-                               # file download error check 
-                               if file_path_list.nil? or file_path_list.empty? then   
-                                       @log.error( "Can't download package file #{pkg_name}" , Log::LV_USER)
-                                       next
-                               else
-                                       @log.info "download binary package successfully: [#{pkg_name}]"
-                                       file_path = file_path_list[0]
-                               end 
-                
-                               # update pkg class  
-                               server_pkg.path = "/binary/#{File.basename(file_path)}"
-                               server_pkg.origin = client_bin.server_addr
-                               @pkg_hash_os[os][pkg_name] = server_pkg 
-
-                               dep_pkg_path_list = dep_pkg_path_list +  server_pkg.source_dep_list
-
-                                # if binary only package, then skip downloading its source
-                               if server_pkg.src_path.empty? then next end
-
-                                # if binary's source package is not downlaoded, download it
-                               if ( not source_pkg_path_list.include? server_pkg.src_path ) then
-                                       @log.info "download source package: [#{server_pkg.src_path}]"
-                                       file = client_src.download_source( pkg_name, os )
-                                       if file.nil? then  
-                                               @log.error "Can't download source package [#{pkg_name}]"
+               # lock
+               lock_file = Utils.file_lock(@lock_file_path)
+
+               # reload pkg list from newest pkg list file
+               reload_distribution_information()
+
+               # update pkg_list hash
+               update_pkg_list.each do |update_option, os, pkg|
+                       # if updated package's os is removed then skip update
+                       if not @support_os_list.include? os then
+                               next
+                       end
+
+                       case update_option
+                       when "ADD"
+                               local_pkg = @pkg_hash_os[os][pkg.package_name]
+
+                               if (not force) and (not local_pkg.nil?) then
+                                       # if updated package 'local' package then skip
+                                       if local_pkg.origin.eql? "local" then
+                                               next
+                                       end
+
+                                       # if package is update when sync time then skip
+                                       if Utils.compare_version(local_pkg.version, pkg.version) == -1 then
+                                               next
                                        else
-                                               source_pkg_path_list.push server_pkg.src_path 
-                                       end 
-                               end
-                       # if package exist only server
-                       elsif ( not server_pkg.nil? ) then
-                               #downnlaod binary package
-                               file_path_list = client_bin.download( pkg_name, os, false )
-                
-                               # file download error check 
-                               if file_path_list.nil? or file_path_list.empty? then   
-                                       @log.error( "Can't download package file #{pkg_name}", Log::LV_USER) 
-                                       next
-                               else
-                                       @log.info "download binary package successfully: [#{pkg_name}]"
-                                       file_path = file_path_list[0]
-                               end 
-                
-                               # update pkg class
-                               server_pkg.path = "/binary/#{File.basename(file_path)}"
-                               server_pkg.origin = client_bin.server_addr
-                               @pkg_hash_os[os][pkg_name] = server_pkg
-                
-                               dep_pkg_path_list = dep_pkg_path_list +  server_pkg.source_dep_list 
-                
-                                # if binary only package, then skip downloading its source
-                               if server_pkg.src_path.empty? then next end
-                
-                                # if binary's source package is not downlaoded, download it
-                               if not source_pkg_path_list.include? server_pkg.src_path then
-                                       @log.info "download source package: [#{server_pkg.src_path}]"
-                                       file = client_src.download_source( pkg_name, os )
-                                       if file.nil? 
-                                               @log.error "Can't download source package [#{server_pkg.src_path}]"
-                                       else 
-                                               source_pkg_path_list.push server_pkg.src_path 
+                                               @log.info( "update package [#{pkg.package_name}] in #{pkg.os}", Log::LV_USER)
                                        end
                                end
-                       # if package exist only local
-                       elsif ( not local_pkg.nil? ) then  
-                               # if pakcage is not local package then server's package is removed 
-                               # so, local package remove
-                               if not local_pkg.origin.eql? "local" then  
-                                       @pkg_hash_os[os].delete(pkg_name)
+
+                               @pkg_hash_os[os][pkg.package_name] = pkg
+                               changes.push "Package: #{pkg.package_name} changes: #{pkg.get_changes}" if pkg.does_change_exist?
+                       when "REMOVE"
+                               if not force then
+                                       if @pkg_hash_os[os][pkg.package_name].origin.eql? "local" then
+                                       else
+                                               @log.info( "remove package [#{pkg.package_name}] in #{pkg.os}", Log::LV_USER)
+                                               next
+                                       end
                                end
+
+                               @pkg_hash_os[os].delete(pkg.package_name)
+                               changes.push "#{pkg.package_name} #{os} removed"
                        else
-                               raise RuntimeError,"hash merge error!"
+                               @log.error("Unsupportd update option : #{update_option}", Log::LV_USER)
+                               next
+                       end
+               end
+
+               update_archive_list.each do |pkg|
+                       if not @archive_pkg_list.include? pkg then
+                               @archive_pkg_list.push pkg
+                               changes.push "Add archive package #{pkg}"
+                               archive_update_flag = true
                        end
                end
 
-               @log.info "pkg file update end"
-               # download dependency source packages 
-               dep_pkg_path_list.uniq.each do |dep|
-                       if dep.package_name.strip.empty? then next end
-                       @log.info "download dep package: [#{dep.package_name}]"
-                       file = client_src.download_dep_source( dep.package_name )
-                       if file.nil? 
-                               @log.error "Can't download dep package [#{dep.package_name}]"
-                       end 
-               end 
+               # update pkg_list file
+               if pkg_list_update_flag then
+                       write_all_pkg_list()
+                       distribution_update_flag = true
+               end
+
+               # update archive list file
+               if archive_update_flag then
+                       write_archive_pkg_list()
+                       distribution_update_flag = true
+               end
+
+               # unlock
+               Utils.file_unlock(lock_file)
+               Utils.file_unlock(sync_lock_file)
+
+               if not changes.empty? then
+                       @last_sync_changes = "SYSTEM: sync parents server \n#{changes.uniq.join("\n\n")}"
+               end
 
-               @log.info "pkg deb file update end"
-               # pakcage list file update
-               write_pkg_list(os)
-               @log.info "write pkg list"
+               return distribution_update_flag
        end
 
-       def sync_archive_pkg
-               client = Client.new( @server_url, "#{@location}/source", @log )
-               client.update 
-
-               downloaded_list = []
-               client.archive_pkg_list.each do |pkg| 
-                       if not File.exist? "#{@location}/source/#{pkg}" then
-                               file = client.download_dep_source(pkg) 
-                               if file.nil? 
-                                       @log.error "Can't download archive package [#{file}]"
-                               else 
-                                       downloaded_list.push pkg
+       def add_os(os)
+               if @support_os_list.include? os then
+                       @log.error("#{os} is already exist ", Log::LV_USER)
+                       return
+               end
+
+               # update os information
+               @support_os_list.push os
+               @pkg_hash_os[os] = {}
+               File.open("#{@location}/#{OS_INFO_FILE}", "a") do |f|
+                       f.puts os
+               end
+
+               # create pkg_list_#{os} file
+               File.open( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f| end
+       end
+
+       def clean( remain_snapshot_list )
+               file_list = []
+               used_archive_list = []
+
+               # collect remaining file's name from current package server version
+               @support_os_list.each do |os|
+                       @pkg_hash_os[os].each_value do |pkg|
+                               file_list.push(pkg.path.sub("/binary/",""))
+
+                               pkg.source_dep_list.each do |source_dep|
+                                       if @archive_pkg_list.include? source_dep.package_name then
+                                               used_archive_list.push source_dep.package_name
+                                       else
+                                               @log.error("Can't find dependency source package : #{source_dep.package_name}")
+                                       end
                                end
                        end
-               end 
+               end
+
+               # remain only used archive package
+               @archive_pkg_list = used_archive_list.uniq
+               write_archive_pkg_list
+
+               # collect remaning file's name from snapshot list
+               remain_snapshot_list.each do |snapshot|
+                       os_info = "#{@location}/snapshots/#{snapshot}/#{OS_INFO_FILE}"
+                       os_list = []
+                       # if snapshot has os_info file then using that file
+                       if File.exist? os_info
+                               File.open( os_info, "r" ) do |f|
+                                       f.each_line do |l|
+                                               os_list.push l.strip
+                                       end
+                               end
+                               # if snapshot does not have os_info file then using package server os_info list
+                       else
+                               os_list = @support_os_list
+                       end
+
+                       os_list.each do |os|
+                               begin
+                                       info_file = "#{@location}/snapshots/#{snapshot}/#{PKG_LIST_FILE_PREFIX}#{os}"
+                                       if not File.exist? info_file then
+                                               @log.error( "pkg list file does not exist : #{info_file}", Log::LV_USER)
+                                               next
+                                       end
+
+                                       pkg_list = Parser.read_repo_pkg_list_from(info_file)
+
+                                       pkg_list.each_value do |pkg|
+                                               file_list.push(pkg.path.sub("/binary/",""))
+                                       end
+                               rescue => e
+                                       @log.error( e.message, Log::LV_USER)
+                               end
+                       end
+
+                       used_archive_list = used_archive_list + read_archive_pkg_list( snapshot )
+               end
+
+               file_list.uniq!
+               used_archive_list.uniq!
+
+               # remove unused binary file
+               Dir.new( @location + "/binary" ).each do |file|
+                       if file.start_with? "." then next end
+
+                       if not file_list.include? file then
+                               FileUtils.rm "#{@location}/binary/#{file}"
+                       end
+               end
+
+               # remove unused archive file
+               Dir.new( @location + "/source" ).each do |file|
+                       if file.start_with? "." then next end
+
+                       if not used_archive_list.include? file then
+                               FileUtils.rm "#{@location}/source/#{file}"
+                       end
+               end
+
+               # remove unused snapshot
+               Dir.new( @location + "/snapshots" ).each do |snapshot|
+                       if snapshot.start_with? "." then next end
+
+                       if not remain_snapshot_list.include? snapshot then
+                               FileUtils.rm_rf "#{@location}/snapshots/#{snapshot}"
+                       end
+               end
+
+               # upate snapshot.info file
+               update_snapshot_info_file(remain_snapshot_list)
+       end
 
-               write_archive_pkg_list( downloaded_list )
-       end 
+       def write_all_pkg_list
+               @support_os_list.each do |os|
+                       write_pkg_list(os)
+               end
+       end
 
        def write_pkg_list( os )
-               File.open( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", "w" ) do |f| 
+               # if input os is empty then return
+               if os.nil? or os.empty? then return end
+
+               # generate temp file
+               tmp_file_name = ""
+               while ( tmp_file_name.empty? )
+                       tmp_file_name = @location + "/temp/." + Utils.create_uniq_name
+
+                       if File.exist? tmp_file_name then
+                               tmp_file_name = ""
+                       end
+               end
+
+               File.open( tmp_file_name, "w" ) do |f|
                        @pkg_hash_os[os].each_value do |pkg|
+                               # insert package information to file
                                pkg.print_to_file(f)
-                               f.puts 
+                               # insert empty line to file
+                               f.puts
                        end
-               end     
-       end
+               end
 
-       def write_archive_pkg_list( pkg_file_name_list )
-               File.open( "#{@location}/#{ARCHIVE_PKG_LIST}", "a" ) do |f| 
-                       pkg_file_name_list.map { |name| f.puts(name) }
-               end     
+               FileUtils.mv( tmp_file_name, "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}", :force => true )
        end
 
-       # input: package file path(zip file) 
-       # return: pkg 
+       # input: package file path(zip file)
+       # return: pkg
        def get_package_from_file(file_path)
-               tmp_dir = "./" + Utils.create_uniq_name
-               FileUtils.mkdir "#{@location}/#{tmp_dir}"
-
-               # file extention is zip 
-               if file_path.end_with? ".zip" then
-                       system("unzip -q #{file_path} pkginfo.manifest -d #{@location}/#{tmp_dir} ")
-               # file extention is tar.gz
-               elsif file_path.end_with? ".tar.gz" or file_path.end_with? ".tar" then
-                       system("tar -xzf #{file_path} -C #{@location}/#{tmp_dir}")
+               tmp_dir = @location + "/" + Utils.create_uniq_name
+
+               #if file extension is .zip then check pkginfo.manifest
+               if File.extname(file_path).eql? ".zip" then
+                       FileUtils.mkdir tmp_dir
+
+                       ret = FileInstaller.extract_a_file(file_path, "pkginfo.manifest", tmp_dir, @log)
                else
-                       raise "unsupported zipping file. just use [zip/tar.gz]"
+                       return nil
                end
-               pkg = Parser.read_pkginfo( "#{@location}/#{tmp_dir}/pkginfo.manifest" )
-               FileUtils.rm_rf "#{@location}/#{tmp_dir}"
 
-               return pkg
-       end 
+               # if pkginfo.manifest file exist
+               if not ret.nil? then
+                       begin
+                               pkg = Parser.read_single_pkginfo_from "#{tmp_dir}/pkginfo.manifest"
+                       rescue => e
+                               @log.error( e.message, Log::LV_USER)
+                               return nil
+                       end
+
+                       FileUtils.rm_rf tmp_dir
+                       return pkg
+                       # if pkginfo.manifest file does not exist
+               else
+                       FileUtils.rm_rf tmp_dir
+                       return nil
+               end
+       end
+
+       def remove_pkg( pkg_name_list, os )
+               if os.eql? "all" then os_list = @support_os_list
+               else os_list = [ os ]
+               end
 
-       def remove_pkg( pkg_name_list )  
-               for package_name in pkg_name_list
-                       removed_flag = false 
+               pkg_name_list.each do |package_name|
+                       removed_flag = false
 
-               for os in SUPPORTED_OS 
-                               if @pkg_hash_os[os].key?(package_name) then 
-                                       @log.info( "remove package [#{package_name}] in #{os}", Log::LV_USER)
-                                       @pkg_hash_os[os].delete(package_name)  
+                       os_list.each do |o|
+                               if not @support_os_list.include? o then
+                                       @log.error( "package server does not support input os : #{o}")
+                                       next
+                               end
+
+                               if @pkg_hash_os[o].key?(package_name) then
+                                       @log.info( "remove package [#{package_name}] in #{o}", Log::LV_USER)
+                                       @pkg_hash_os[o].delete(package_name)
                                        removed_flag = true
                                end
-                       end  
+                       end
 
-                       if not removed_flag then 
-                               @log.error( "Can't find package: #{package_name}", Log::LV_USER)
+                       if not removed_flag then
+                               if @archive_pkg_list.include? package_name then
+                                       @archive_pkg_list.delete package_name
+                               else
+                                       @log.error( "Can't find package: [#{package_name}]", Log::LV_USER)
+                               end
                        end
-               end 
+               end
 
                # check install dependency integrity
-               check_instll_dependency_integrity 
+               if @integrity.eql? "YES" then
+                       @log.info "integrity check"
+                       check_integrity
+               else
+                       @log.info "skip integrity check"
+               end
+
 
-        for os in SUPPORTED_OS 
-                       write_pkg_list(os) 
+               # update pkg_list file
+               os_list.each do |o|
+                       write_pkg_list(o)
                end
-       end 
+               write_archive_pkg_list
+       end
 
-       def check_instll_dependency_integrity 
-               @log.info "check server pkg's install dependency integrity" 
+       def remove_snapshot( snapshot_list )
+               remain_snapshot = []
+               removed_snapshot = []
 
-               for os in SUPPORTED_OS 
-                       for pkg in @pkg_hash_os[os].each_value 
-                               error_msg = "[#{pkg.package_name}]'s install dependency not matched in "  
+               # remove unused snapshot
+               Dir.new( @location + "/snapshots" ).each do |snapshot|
+                       if snapshot.start_with? "." then next end
 
-                               for dep in pkg.install_dep_list  
-                                       if @pkg_hash_os[os].has_key? dep.package_name then   
-                                               target_pkg = @pkg_hash_os[os][dep.package_name]
-                                       else 
-                                               raise RuntimeError,(error_msg + dep.to_s) 
-                                       end
-                               
-                                       # TODO: check just install dependency exist
-                                       next 
-                                       
-                                       # check package's version 
-                                       if not dep.match? target_pkg.version then 
-                                               raise RuntimeError,(error_msg + dep.to_s)
-                                       end 
-
-                                       # TODO: install dependency's os is always ture
-                                       #if not dep.target_os_list.length == 0 then 
-                                       #       if not dep.target_os_list.include? target_pkg.os then  
-                                       #               raise RuntimeError,(error_msg + dep.to_s)
-                                       #       end 
-                                       #end 
-                               end 
-
-                               # TODO: check just install dependency 
-                               next 
-
-                               error_msg = "[#{pkg.package_name}]'s build dependency not matched in "  
-                               for dep in pkg.build_dep_list 
-                                       if dep.target_os_list.length == 0 then
-                                               build_dep_os = os  
+                       if snapshot_list.include? snapshot then
+                               FileUtils.rm_rf "#{@location}/snapshots/#{snapshot}"
+                               snapshot_list.delete snapshot
+                               removed_snapshot.push snapshot
+                       else
+                               remain_snapshot.push snapshot
+                       end
+               end
+
+               if not snapshot_list.empty? then
+                       @log.output( "snapshot not exist : #{snapshot_list.join(",")}", Log::LV_USER )
+               end
+
+               if not removed_snapshot.empty? then
+                       @log.output( "snapshot removed: #{removed_snapshot.join(",")}", Log::LV_USER )
+               end
+
+               update_snapshot_info_file(remain_snapshot)
+       end
+
+       def check_integrity
+               @log.info "check server pkg's install dependency integrity"
+
+               @support_os_list.each do |os|
+                       @pkg_hash_os[os].each_value.each do |pkg|
+                               check_package_integrity(pkg)
+                       end
+               end
+       end
+
+       def check_package_integrity(pkg)
+               error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s install dependency not matched in "
+               os = pkg.os
+
+               pkg.install_dep_list.each do |dep|
+                       if @pkg_hash_os[os].has_key? dep.package_name then
+                               target_pkg = @pkg_hash_os[os][dep.package_name]
+                       else
+                               raise RuntimeError,(error_msg + dep.to_s)
+                       end
+
+                       # check package's version
+                       if not dep.match? target_pkg.version then
+                               raise RuntimeError,(error_msg + dep.to_s)
+                       end
+
+               end
+
+               error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s build dependency not matched in "
+               pkg.build_dep_list.each do |dep|
+                       if dep.target_os_list.length == 0 then
+                               build_dep_os = os
+                       else
+                               build_dep_os = dep.target_os_list[0]
+                       end
+
+                       if @pkg_hash_os[build_dep_os].has_key? dep.package_name then
+                               target_pkg = @pkg_hash_os[build_dep_os][dep.package_name]
+                       else
+                               raise RuntimeError,(error_msg + dep.to_s)
+                       end
+
+                       # check package's version
+                       if not dep.match? target_pkg.version then
+                               raise RuntimeError,(error_msg + dep.to_s)
+                       end
+               end
+
+               error_msg = "[[#{pkg.package_name}] in #{pkg.os}]'s source dependency not matched in "
+               pkg.source_dep_list.each do |dep|
+                       if not @archive_pkg_list.include? dep.package_name then
+                               raise RuntimeError,(error_msg + dep.to_s)
+                       end
+               end
+       end
+
+       def read_archive_pkg_list( snapshot_name )
+               pkg_list = []
+
+               if snapshot_name.empty?
+                       file_name = @location + "/" + ARCHIVE_PKG_FILE
+               else
+                       file_name = @location + "/snapshots/" + snapshot_name + "/" + ARCHIVE_PKG_FILE
+               end
+
+               if File.exist? file_name
+                       File.open(file_name, "r") do |f|
+                               f.each_line do |l|
+                                       pkg_list.push(l.strip)
+                               end
+                       end
+               end
+
+               return pkg_list
+       end
+
+       def write_archive_pkg_list()
+               File.open( "#{@location}/#{ARCHIVE_PKG_FILE}", "w" ) do |f|
+                       @archive_pkg_list.each do |pkg|
+                       f.puts(pkg)
+               end
+               end
+       end
+
+       def initialize_pkg_list
+               if not File.exist? "#{@location}/#{OS_INFO_FILE}" then
+                       return
+               end
+
+               # get support_os_list
+               @support_os_list = []
+               File.open( "#{@location}/#{OS_INFO_FILE}", "r" ) do |f|
+                       f.each_line do |l|
+                       @support_os_list.push l.strip
+               end
+               end
+
+               # read package_list file
+               @support_os_list.each do |os|
+                       @pkg_hash_os[os] = {}
+                       pkg_list_file = "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}"
+
+                       if File.exist? pkg_list_file then
+                               begin
+                                       @pkg_hash_os[os] = Parser.read_repo_pkg_list_from( pkg_list_file )
+                               rescue => e
+                                       @log.error( e.message, Log::LV_USER)
+                                       @pkg_hash_os[os] = nil
+                               end
+                       end
+               end
+
+               # read archive package_list file
+               @archive_pkg_list = read_archive_pkg_list("")
+       end
+
+       def get_link_package(pkg, pkg_os)
+               pkg.os_list.each do |os|
+                       # skip in same os for origin package
+                       if pkg_os.eql? os then next end
+                       # skip in unsupported os
+                       if not @support_os_list.include? os then next end
+
+                       exist_pkg = @pkg_hash_os[os][pkg.package_name]
+                       if exist_pkg.nil? then next end
+
+                       compare_version = Utils.compare_version(pkg.version, exist_pkg.version)
+                       # if version same then compatible package
+                       if compare_version == 0 then
+                               return exist_pkg
+                       end
+               end
+
+               return nil
+       end
+
+       # PRIVATE METHODS/VARIABLES
+       private
+
+       def sync_package( pkg_name, client, os, force )
+               server_pkg = client.pkg_hash_os[os][pkg_name]
+               local_pkg = @pkg_hash_os[os][pkg_name]
+
+               # if server and local has package
+               if ( not server_pkg.nil? ) and ( not local_pkg.nil? ) then
+                       version_cmp = Utils.compare_version( local_pkg.version, server_pkg.version )
+                       if ( version_cmp == 0 ) then
+                               # version is same then skip update
+                               return nil
+                       end
+
+                       if ( version_cmp == -1 ) then
+                               # local package's version is higher than server packages's version then skip update
+                               return nil
+                       end
+
+                       if ( local_pkg.origin.eql? "local" ) and (not force) then
+                               # local_pkg is generated from local and not force mode then skip update
+                               return nil
+                       end
+
+                       pkg = sync_package2( server_pkg, client, os )
+                       return ["ADD", os, pkg]
+                       # if package exist only server
+               elsif ( not server_pkg.nil? ) then
+                       pkg = sync_package2( server_pkg, client, os )
+                       return ["ADD", os, pkg]
+                       # if package exist only local
+               elsif ( not local_pkg.nil? ) then
+                       # if local pkg is generated from local then skip
+                       if local_pkg.origin.eql? "local" and (not force) then
+                               return nil
+                       end
+
+                       # package remove
+                       return ["REMOVE", os, local_pkg]
+               else
+                       raise RuntimeError,"hash merge error!"
+               end
+
+               return nil
+       end
+
+       def sync_package2( pkg, client, os )
+               pkg_name = pkg.package_name
+
+               # package update
+               file_path_list = client.download( pkg_name, os, false )
+
+               # file download error check
+               if file_path_list.nil? or file_path_list.empty? then
+                       @log.error("Can't download package file [#{pkg_name}]", Log::LV_USER)
+                       return nil
+               else
+                       file_path = file_path_list[0]
+               end
+
+               # update pkg class
+               pkg.path = "/binary/#{File.basename(file_path)}"
+               pkg.origin = client.server_addr
+               return pkg
+
+       end
+
+       def update_snapshot_info_file(remain_snapshot_list)
+               if not File.exist? "#{@location}/#{SNAPSHOT_INFO_FILE}"
+                       @log.error "Can not find snapshot info file"
+                       return
+               end
+
+               # generate temp file
+               tmp_file_name = ""
+               while ( tmp_file_name.empty? )
+                       tmp_file_name = @location + "/temp/." + Utils.create_uniq_name
+
+                       if File.exist? tmp_file_name then
+                               tmp_file_name = ""
+                       end
+               end
+
+               # modify snapshot info File
+               info_file = File.readlines("#{@location}/#{SNAPSHOT_INFO_FILE}")
+               File.open(tmp_file_name, 'w') do |f|
+                       save_flag = false
+                       info_file.each do  |line|
+                               if line =~ /name :/ then
+                                       if remain_snapshot_list.include? line.split(':')[1].strip then
+                                               save_flag = true
                                        else
-                                               build_dep_os = dep.target_os_list[0]
+                                               save_flag = false
                                        end
 
-                                       if @pkg_hash_os[build_dep_os].has_key? dep.package_name then   
-                                               target_pkg = @pkg_hash_os[build_dep_os][dep.package_name]
-                                       else 
-                                               raise RuntimeError,(error_msg + dep.to_s) 
-                                       end
-                                       
-                                       # check package's version 
-                                       if not dep.match? target_pkg.version then 
-                                               raise RuntimeError,(error_msg + dep.to_s)
-                                       end 
-
-                                       # TODO: check package's target_os   
-                                       #if not dep.target_os_list.length == 0 then 
-                                       #       if not dep.target_os_list.include? target_pkg.os then  
-                                       #               raise RuntimeError,(error_msg + dep.to_s)
-                                       #       end 
-                                       #end 
-                               end 
-
-                               error_msg = "[#{pkg.package_name}]'s source dependency not matched in "  
-                               for dep in pkg.source_dep_list 
-                                       # check source package exist
-                                       if not File.exist? "#{@location}/source/#{dep.package_name}"
-                                               raise RuntimeError,(error_msg + dep.to_s)
-                                       end 
-                               end 
-                       end
-               end 
+                               end
+
+                               if save_flag then
+                                       f.puts line
+                               end
+                       end
+               end
+
+               FileUtils.mv( tmp_file_name, "#{@location}/#{SNAPSHOT_INFO_FILE}", :force => true )
+       end
+
+       def get_all_reverse_depends_pkgs(pkg, checked_list)
+               depends_list = []
+
+               @support_os_list.each do |os|
+                       @pkg_hash_os[os].each_value do |dpkg|
+                               if dpkg.install_dep_list.include? pkg or \
+                                       dpkg.build_dep_list.include? pkg then
+                                       depends_list.push opkg
+                               end
+
+                       end
+               end
+
+               depends_list.each do |dpkg|
+                       checked_list.push dpkg
+                       rdepends_list = get_all_reverse_depends_pkgs( dpkg, checked_list )
+               end
+
+               return rdepends_list
+       end
+
+       def reload_distribution_information
+               if not File.exist?("#{@location}/#{OS_INFO_FILE}") then
+                       return
+               end
+
+               # get support_os_list
+               @support_os_list = []
+               File.open( "#{@location}/#{OS_INFO_FILE}", "r" ) do |f|
+                       f.each_line do |l|
+                       @support_os_list.push l.strip
+               end
+               end
+
+               # read binary package_list file
+               @support_os_list.each do |os|
+                       @pkg_hash_os[os] = {}
+                       pkg_list_file = "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}"
+
+                       if File.exist? pkg_list_file then
+                               begin
+                                       @pkg_hash_os[os] = Parser.read_repo_pkg_list_from( pkg_list_file )
+                               rescue => e
+                                       @log.error( e.message, Log::LV_USER)
+                                       @pkg_hash_os[os] = nil
+                               end
+                       end
+               end
+
+               # read archive package_list file
+               @archive_pkg_list = read_archive_pkg_list( "" )
+       end
+
+       def remove_os(os)
+               if not @support_os_list.include? os then
+                       @log.error("Can't remove os : #{os} does not exist ", Log::LV_USER)
+               end
+
+               # update os information
+               @support_os_list.delete os
+               @pkg_hash_os.delete os
+
+               # generate temp file
+               tmp_file_name = ""
+               while ( tmp_file_name.empty? )
+                       tmp_file_name = @location + "/temp/." + Utils.create_uniq_name
+
+                       if File.exist? tmp_file_name then
+                               tmp_file_name = ""
+                       end
+               end
+
+               info_file = File.readlines("#{@location}/#{OS_INFO_FILE}")
+               File.open(tmp_file_name, "w") do |f|
+                       info_file.each do |line|
+                               if not line.strip.eql? os then
+                                       f.puts line
+                               end
+                       end
+               end
+
+               FileUtils.mv( tmp_file_name, "#{@location}/#{OS_INFO_FILE}", :force => true )
+
+               # delete pkg_list_#{os} file
+               File.delete( "#{@location}/#{PKG_LIST_FILE_PREFIX}#{os}" )
+       end
+
+       def sync_archive_pkg
+               client = Client.new( @server_url, "#{@location}/source", @log )
+
+               download_list = client.archive_pkg_list - @archive_pkg_list
+
+               updated_file_list = []
+
+               # if update list is empty then return empty array
+               if download_list.empty? then return updated_file_list end
+
+               download_list.each do |pkg|
+                       file = client.download_dep_source(pkg)
+                       if file.nil?
+                               @log.error("Can't download archive package [#{pkg}]", Log::LV_USER)
+                       else
+                               updated_file_list.push pkg
+                       end
+               end
+
+               return updated_file_list
        end
+
 end
index 03082080a04b118469abfbc71cdd08c64886d31b..b5dd1ec9ce01f57ccc52a0a4552b43a57bf73fe0 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- downloader.rb 
+
+ downloader.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -31,38 +31,40 @@ require "utils"
 
 class FileDownLoader
 
-    @@log = nil
-
-    def FileDownLoader.set_logger(logger)
-        @@log = logger
-    end
-
-    def FileDownLoader.download(url, path)
-        ret = false
-
-        if not File.directory? path then
-            @@log.error "\"#{path}\" does not exist"
-            return ret
-        end
-        
-        is_remote = Utils.is_url_remote(url)
-        filename = url.split('/')[-1]
-
-        fullpath = File.join(path, filename)
-
-        if is_remote then
-            ret = system "wget #{url} -O #{fullpath} -nv"
-        else
-            if not File.exist? url then
-                @@log.error "\"#{url}\" file does not exist"
-                return false
-            else
-                ret = system "cp #{url} #{fullpath}"
-            end
-        end
-
-        # need verify
-        return ret
-    end
+       def FileDownLoader.download(url, path, logger)
+               ret = false
+
+               if not File.directory? path then
+                       logger.error "\"#{path}\" does not exist"
+                       return ret
+               end
+
+               is_remote = Utils.is_url_remote(url)
+               filename = url.split('/')[-1]
+               fullpath = File.join(path, filename)
+
+               logger.info "Downloading #{url}"
+               if is_remote then
+                       pid,status = Utils.execute_shell_with_log( "wget #{url} -O #{fullpath} -nv --tries=3", logger.path )
+                       ret = (not status.nil? and status.exitstatus != 0) ? false : true
+                       #ret = Utils.execute_shell( "wget #{url} -O #{fullpath} -q")
+               else
+                       if not File.exist? url then
+                               logger.error "\"#{url}\" file does not exist"
+                               return false
+                       else
+                               ret = system "cp #{url} #{fullpath}"
+                       end
+               end
+
+               # need verify
+               if ret then
+                       logger.info "Downloaded #{filename}.. OK"
+               else
+                       logger.info "Failed to download #{filename}"
+                       logger.info "  [dist: #{path}]"
+               end
+               return ret
+       end
 end
 
index 0006b8da4e8208e1f804f76ed80035ae55eee3fe..58febe91ab98f3ab5cba408248d79ec000ff72b6 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- installer.rb 
+
+ installer.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -28,273 +28,462 @@ Contributors:
 
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
-require "serverConfig"
+require "packageServerConfig"
 require "log"
 require "utils"
+if Utils.is_windows_like_os( Utils::HOST_OS ) then
+       require "rubygems"
+       require "zip/zip"
+end
 
 class FileInstaller
 
-    CONFIG_PATH = "#{$build_tools}/client"
-    PACKAGE_INFO_DIR = ".info"
-
-    @@log = nil
-
-    def FileInstaller.set_logger(logger)
-        @@log = logger
-    end
-
-    def FileInstaller.install(package_name, package_file_path, type, target_path)
-
-        if not File.exist? package_file_path then
-            @@log.error "\"#{package_file_path}\" file does not exist."
-            return false
-        end
-
-        case type
-        # install script when binary package
-        when "binary" then
-            uniq_name = Utils.create_uniq_name
-            path = Utils::HOME + "/tmp/#{uniq_name}"
-            if Utils::HOST_OS.eql? "windows" then
-                drive = Utils::HOME.split("/")[0]
-                path = "#{drive}/#{uniq_name}"
-            end
-            FileUtils.mkdir_p "#{path}"
-
-            if File.directory? path then
-               log = "##### create temporary dir : #{path} #####\n"
-            else
-               log = "##### [Failed] create temporary dir : #{path} #####\n"
-               return false 
-            end
-
-            log = log + "##### extract file : #{package_file_path} #####\n"
-            log = log + extract_file(package_name, package_file_path, path, target_path)
-            move_dir(package_name, path, target_path)
-
-            log = log + "##### execute install script #####\n"
-            log = log + execute_install_script(package_name, path, target_path)
-
-            log = log + "##### move remove script #####\n"
-            move_remove_script(package_name, path, target_path)
-
-            log = log + "##### remove temporary dir : #{path} #####\n"
-            Utils.execute_shell("rm -rf #{path}")
-
-            target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-            FileUtils.mkdir_p(target_config_path)
-            pkg_inst_log = "#{package_name}_inst.log"
-            pkg_inst_log_path = File.join(target_config_path, pkg_inst_log)
-
-            File.open(pkg_inst_log_path, "a+") do |f|
-                f.puts log
-            end
-
-        when "source" then
-        end
-
-        # need verify
-        return true;
-    end
-
-    def FileInstaller.move_remove_script(package_name, path, target_path)
-        target_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-        FileUtils.mkdir_p(target_path)
-        script_file_prefix = "#{path}/remove.*"
-        script_file = Dir.glob(script_file_prefix)[0]
-
-        if not script_file.nil? then
-            FileUtils.mv(script_file, target_path)
-        end
-    end 
-
-
-    def FileInstaller.execute_install_script(package_name, path, target_path)
-        script_file_prefix = "#{path}/install.*"
-        script_file = Dir.glob(script_file_prefix)[0]
-        log = ""
-        
-        if not script_file.nil? then
-            @@log.info "Execute \"#{script_file}\" file"
-            cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
-            log = `#{cmd}`
-        end
-        return log
-    end
-
-    def FileInstaller.execute_remove_script(package_name, target_path)
-        info_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-        if not File.directory? info_path then
-            return false
-        end
-
-        script_file_prefix = "#{info_path}/remove.*"
-        script_file = Dir.glob(script_file_prefix)[0]
-        log = ""
-
-        if not script_file.nil? then
-            @@log.info "Execute \"#{script_file}\" file"
-            cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
-            log = `#{cmd}`
-        end
-    end
-
-    def FileInstaller.remove_pkg_files(package_name, target_path)
-        list_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-
-        if not File.directory? list_path then
-            return false
-        end
-
-        list_file_name = "#{list_path}/#{package_name}.list"
-        list_file = Dir.glob(list_file_name)[0]
-        directories = []
-
-        if not list_file.nil? then
-            File.open(list_file, "r") do |file|
-                file.each_line do |f|
-                    f = f.strip
-                    if f.nil? or f.empty? then next end
-                    file_path = File.join(target_path, f)
-                    if File.directory? file_path then
-                        if File.symlink? file_path then 
-                            File.unlink file_path
-                            next
-                        end
-                        entries = Dir.entries(file_path)
-                        if entries.include? "." then entries.delete(".") end
-                        if entries.include? ".." then entries.delete("..") end
-                        if entries.empty? or entries.nil? then
-                            begin
-                                Dir.rmdir(file_path)
-                            rescue SystemCallError
-                                @@log.warn "\"#{file_path}\" directory is not empty"
-                            end 
-                        else directories.push(file_path) end
-                    elsif File.file? file_path then FileUtils.rm_f(file_path)
-                    elsif File.symlink? file_path then File.unlink file_path 
-                    # if files are already removed by remove script,
-                    else @@log.warn "\"#{file_path}\" does not exist" end
-                end
-            end
-
-            directories.reverse.each do |path|
-                entries = Dir.entries(path)
-                if entries.include? "." then entries.delete(".") end
-                if entries.include? ".." then entries.delete("..") end
-                if entries.empty? or entries.nil? then
-                begin
-                    Dir.rmdir(path)
-                rescue SystemCallError
-                    @@log.warn "\"#{file_path}\" directory is not empty"
-                end 
-                else next end
-           end
-        end
-        #FileUtils.rm_rf(list_path)
-        Utils.execute_shell("rm -rf #{list_path}")
-        return true
-    end
-
-    def FileInstaller.uninstall(package_name, type, target_path)
-        case type
-        when "binary" then
-            execute_remove_script(package_name, target_path)
-            remove_pkg_files(package_name, target_path)
-        when "source" then
-        end
-
-        return true
-    end
-
-    def FileInstaller.move_dir(package_name, source_path, target_path)
-        config_path = File.join(target_path, PACKAGE_INFO_DIR, package_name)
-        FileUtils.cp_r Dir.glob("#{source_path}/data/*"), target_path
-        FileUtils.cp "#{source_path}/pkginfo.manifest", config_path
-    end
-
-    def FileInstaller.extract_file(package_name, package_file_path, path, target_path)
-        dirname = File.dirname(package_file_path)
-        filename = File.basename(package_file_path)
-        ext = File.extname(filename)
-
-        target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
-        FileUtils.mkdir_p(target_config_path)
-        pkg_file_list = "#{package_name}.list"
-        pkg_file_list_path = File.join(target_config_path, pkg_file_list)
-        temp_pkg_file_list = "temp_file_list"
-        temp_pkg_file_list_path = File.join(target_config_path, "temp_file_list")
-
-        show_file_list_command = nil
-        extrach_file_list_command = nil
-
-        case ext
-        when ".zip" then
-            show_file_list_command = "zip -sf #{package_file_path}"
-            extract_file_list_command = "unzip \"#{package_file_path}\" -d \"#{path}\""
-        when ".tar" then
-            show_file_list_command = "tar -sf #{package_file_path}"
-            extract_file_list_command = "tar xf \"#{package_file_path}\" -C \"#{path}\""
-        else
-            @@log.error "\"#{filename}\" is not supported."
-            return nil 
-        end
-
-        system "#{show_file_list_command} > #{temp_pkg_file_list_path}"
-        File.open(pkg_file_list_path, "a+") do |targetfile|
-            File.open(temp_pkg_file_list_path, "r") do |sourcefile|
-                sourcefile.each_line do |l|
-                    if l.strip.start_with? "data/" then
-                        ml = l.strip[5..-1]
-                        targetfile.puts ml
-                    else next end
-                end
-            end
-        end
-
-        File.delete(temp_pkg_file_list_path)
-        log = `#{extract_file_list_command}`
-        @@log.info "Extracted \"#{filename}\" file.."
-        if log.nil? then log = "" end
-        return log
-    end
-
-    def FileInstaller.extract_specified_file(package_file_path, target_file, path)
-        dirname = File.dirname(package_file_path)
-        filename = File.basename(package_file_path)
-        ext = File.extname(filename)
-        
-        case ext
-        when ".zip" then
-            if not path.nil? then
-                extract_file_command = "unzip -x #{package_file_path} #{target_file} -d #{path}"
-            else
-                extract_file_command = "unzip -x #{package_file_path} #{target_file}"
-            end
-        when ".tar" then
-            if not path.nil? then
-                path = File.join(path, package_file_path)
-                extract_file_command = "tar xvf #{package_file_path} #{target_file}"
-            else
-                extract_file_command = "tar xvf #{package_file_path} #{target_file}"
-            end
-        end
-
-        system "#{extract_file_command}"
-        
-        if not path.nil? then
-            target_file_path = File.join(path, target_file)
-        else
-            target_file_path = target_file
-        end
-
-        if File.exist? target_file_path then
-            @@log.info "Extracted \"#{target_file}\" file.."
-            return true
-        else
-            @@log.info "Failed to extracted \"#{target_file}\" file.."
-            return false
-        end
-    end
+       CONFIG_PATH = "#{PackageServerConfig::CONFIG_ROOT}/client"
+       PACKAGE_INFO_DIR = ".info"
+       PACKAGE_MANIFEST = "pkginfo.manifest"
+
+       def FileInstaller.install(package_name, package_file_path, type, target_path, logger)
+
+               if not File.exist? package_file_path then
+                       logger.error "\"#{package_file_path}\" file does not exist."
+                       return false
+               end
+
+               case type
+                       # install script when binary package
+               when "binary" then
+                       uniq_name = Utils.create_uniq_name
+                       path = Utils::HOME + "/tmp/#{uniq_name}"
+                       # windows has limitation for file path length
+                       if Utils.is_windows_like_os( Utils::HOST_OS ) then
+                               drive = Utils::HOME.split("/")[0]
+                               path = "#{drive}/#{uniq_name}"
+                       end
+                       if not File.exist? path then FileUtils.mkdir_p "#{path}" end
+
+                       if File.directory? path then
+                               log = "## create temporary dir : #{path}\n"
+                       else
+                               logger.error "Failed to create temporary dir"
+                               logger.info "  [path: #{path}]"
+                               return false
+                       end
+
+                       begin
+                               logger.info "Installing \"#{package_name}\" package.."
+                               logger.info "  [file: #{package_file_path}]"
+
+                               log = log + "## Extract file : #{package_file_path}\n"
+                               result = extract_file(package_name, package_file_path, path, target_path, logger)
+                               if result == "" or result.nil? then
+                                       write_log(target_path, package_name, log)
+                                       return false
+                               else log = log + result end
+
+                               log = log + "## Move files : \"#{path}\" to \"#{target_path}\"\n"
+                               result = move_dir(package_name, path, target_path, logger)
+                               if result.nil? then
+                                       write_log(target_path, package_name, log)
+                                       return false
+                               else log = log + result end
+
+                               log = log + "## Execute install script\n"
+                               result = execute_install_script(package_name, path, target_path, logger)
+                               if result.nil? then
+                                       write_log(target_path, package_name, log)
+                                       return false
+                               else log = log + result end
+
+                               log = log + "## Move remove script\n"
+                               result = move_remove_script(package_name, path, target_path, logger)
+                               if result.nil? then
+                                       write_log(target_path, package_name, log)
+                                       return false
+                               else log = log + result end
+
+                               log = log + "## Remove temporary dir : #{path} #####\n"
+                               result = Utils.execute_shell_return("rm -rf #{path}")
+                               if result.nil? then
+                                       logger.warn "Failed to remove temporary path"
+                                       logger.info "  [path: #{path}]"
+                               end
+                       rescue Interrupt
+                               logger.error "FileInstaller: Interrupted.."
+                               Utils.execute_shell("rm -rf #{path}")
+                               logger.info "Removed #{path}"
+                               raise Interrupt
+                       end
+                       write_log(target_path, package_name, log)
+=begin
+                       target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
+                       if not File.exist? target_config_path then FileUtils.mkdir_p(target_config_path) end
+                       pkg_inst_log = "#{package_name}_inst.log"
+                       pkg_inst_log_path = File.join(target_config_path, pkg_inst_log)
+
+                       File.open(pkg_inst_log_path, "a+") do |f|
+                               f.puts log
+                       end
+=end
+               when "source" then
+               end
+
+               # need verify
+               logger.info "Installed \"#{package_name}\" package.. OK"
+               logger.info "  [path: #{target_path}]"
+               return true;
+       end
+
+       def FileInstaller.write_log(target_path, package_name, log)
+               target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
+               if not File.exist? target_config_path then FileUtils.mkdir_p(target_config_path) end
+               pkg_inst_log = "#{package_name}_inst.log"
+               pkg_inst_log_path = File.join(target_config_path, pkg_inst_log)
+
+               File.open(pkg_inst_log_path, "a+") do |f|
+                       f.puts log
+               end
+       end
+
+       def FileInstaller.move_remove_script(package_name, path, target_path, logger)
+               target_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
+               if not File.exist? target_path then FileUtils.mkdir_p(target_path) end
+               script_file_prefix = "#{path}/remove.*"
+               script_file = Dir.glob(script_file_prefix)[0]
+               log = ""
+
+               if not script_file.nil? then
+                       result = Utils.execute_shell_return("mv #{script_file} #{target_path}")
+                       if result.nil? then
+                               logger.error "Failed to move a remove script"
+                               logger.info "  [file: #{script_file}]"
+                               logger.info "  [from: #{path}]"
+                               logger.info "  [to: #{target_path}]"
+                               return nil
+                       else log = result.join("") end
+                       logger.info "Moved remove script file.. OK"
+                       log = log + "[file: #{script_file}]\n"
+                       log = log + "[from: #{path}]\n"
+                       log = log + "[to: #{target_path}]\n"
+               end
+
+               return log
+       end
+
+
+       # Does not verify that the script execution is successful.
+       # Register shortcut should be failed.
+       def FileInstaller.execute_install_script(package_name, path, target_path, logger)
+               script_file_prefix = "#{path}/install.*"
+               script_file = Dir.glob(script_file_prefix)[0]
+               log = ""
+
+               if not script_file.nil? then
+                       logger.info "Execute \"#{script_file}\" file"
+                       if Utils.is_windows_like_os( Utils::HOST_OS ) then
+                               target_path = target_path.gsub("/","\\")
+                               cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
+                       else
+                               `chmod +x #{script_file}`
+                               cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}"
+                       end
+                       logger.info "  [cmd: #{cmd}]"
+                       log = `#{cmd}`
+                       logger.info "Executed install script file.. OK"
+                       log = log + "[file: #{script_file}]\n"
+                       log = log + "[cmd: #{cmd}]\n"
+               end
+
+               return log
+       end
+
+       # Does not verify that the script execution is successful.
+       # Removing shortcut should be failed.
+       def FileInstaller.execute_remove_script(package_name, target_path, logger)
+               info_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
+               if not File.directory? info_path then
+                       logger.error "\"#{info_path}\" does not exist."
+                       return nil
+               end
+
+               script_file_prefix = "#{info_path}/remove.*"
+               script_file = Dir.glob(script_file_prefix)[0]
+               log = ""
+
+               if not script_file.nil? then
+                       logger.info "Execute \"#{script_file}\" file"
+                       if Utils.is_windows_like_os( Utils::HOST_OS ) then
+                               target_path = target_path.gsub("/","\\")
+                               cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
+                       else
+                               `chmod +x #{script_file}`
+                               cmd = "INSTALLED_PATH=\"#{target_path}\" #{script_file}"
+                       end
+                       logger.info "  [cmd: #{cmd}]"
+                       log = `#{cmd}`
+                       logger.info "Executed remote script file.. OK"
+                       log = log + "[file: #{script_file}]\n"
+                       log = log + "[cmd: #{cmd}]\n"
+               end
+
+               return log
+       end
+
+       def FileInstaller.remove_pkg_files(package_name, target_path, logger)
+               list_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
+
+               if not File.directory? list_path then
+                       logger.error "\"#{list_path}\" does not exist."
+                       return false
+               end
+
+               list_file_name = "#{list_path}/#{package_name}.list"
+               list_file = Dir.glob(list_file_name)[0]
+               directories = []
+
+               if not list_file.nil? then
+                       File.open(list_file, "r") do |file|
+                               file.each_line do |f|
+                                       f = f.strip
+                                       if f.nil? or f.empty? then next end
+                                       file_path = File.join(target_path, f)
+                                       if File.directory? file_path then
+                                               if File.symlink? file_path then
+                                                       File.unlink file_path
+                                                       next
+                                               end
+                                               entries = Dir.entries(file_path)
+                                               if entries.include? "." then entries.delete(".") end
+                                               if entries.include? ".." then entries.delete("..") end
+                                               if entries.empty? or entries.nil? then
+                                                       begin
+                                                               Dir.rmdir(file_path)
+                                                       rescue SystemCallError
+                                                               logger.warn "\"#{file_path}\" directory is not empty"
+                                                       end
+                                               else directories.push(file_path) end
+                                       elsif File.file? file_path then FileUtils.rm_f(file_path)
+                                       elsif File.symlink? file_path then File.unlink file_path
+                                               # if files are already removed by remove script,
+                                       else logger.warn "\"#{file_path}\" does not exist" end
+                               end
+                       end
+
+                       directories.reverse.each do |path|
+                               if not File.directory? path     then next end
+                               entries = Dir.entries(path)
+                               if entries.include? "." then entries.delete(".") end
+                               if entries.include? ".." then entries.delete("..") end
+                               if entries.empty? or entries.nil? then
+                                       begin
+                                               Dir.rmdir(path)
+                                       rescue SystemCallError
+                                               logger.warn "\"#{file_path}\" directory is not empty"
+                                       end
+                               else next end
+                       end
+               end
+               Utils.execute_shell("rm -rf #{list_path}")
+               return true
+       end
+
+       def FileInstaller.uninstall(package_name, type, target_path, logger)
+               case type
+               when "binary" then
+                       result = execute_remove_script(package_name, target_path, logger)
+                       if result.nil? then return false end
+                       if not remove_pkg_files(package_name, target_path, logger) then return false end
+               when "source" then
+               end
+
+               return true
+       end
+
+       def FileInstaller.move_dir(package_name, source_path, target_path, logger)
+               config_path = File.join(target_path, PACKAGE_INFO_DIR, package_name)
+               pkginfo_path = File.join(source_path, PACKAGE_MANIFEST)
+               data_path = File.join(source_path, "data")
+               log = ""
+
+               if not File.exist? pkginfo_path then
+                       logger.error "#{PACKAGE_MANIFEST} file does not exist. Check #{source_path}"
+                       return nil
+               else FileUtils.cp pkginfo_path, config_path end
+
+               if File.exist? data_path then
+                       if Dir.entries(data_path).count > 2 then
+                               # if os is linux, use cpio. it is faster than cp
+                               if Utils.is_linux_like_os( Utils::HOST_OS ) then
+                                       absolute_path = `readlink -f #{target_path}`
+                                       result = Utils.execute_shell_return("cd #{data_path}; find . -depth | cpio -pldm #{absolute_path}")
+                               else
+                                       result = Utils.execute_shell_return("cp -r #{data_path}/* #{target_path}")
+                               end
+                               if result.nil? then
+                                       logger.error "Failed to move files"
+                                       logger.info "  [from: #{source_path}]"
+                                       logger.info "  [to:  #{target_path}]"
+                                       return nil
+                               end
+                               logger.info "Moved files.. OK"
+                               log = log + "[from: #{source_path}]\n"
+                               log = log + "[to:  #{target_path}]\n"
+                       end
+               else logger.warn "\"data\" directory does not exist." end
+
+               return log
+       end
+
+       def FileInstaller.extract_file(package_name, package_file_path, path, target_path, logger)
+               dirname = File.dirname(package_file_path)
+               filename = File.basename(package_file_path)
+               ext = File.extname(filename)
+
+               target_config_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
+               if not File.exist? target_config_path then FileUtils.mkdir_p(target_config_path) end
+               pkg_file_list = "#{package_name}.list"
+               pkg_file_list_path = File.join(target_config_path, pkg_file_list)
+               temp_pkg_file_list = "temp_file_list"
+               temp_pkg_file_list_path = File.join(target_config_path, "temp_file_list")
+
+               show_file_list_command = nil
+               extrach_file_list_command = nil
+               log = ""
+
+               case ext
+               when ".zip" then
+                       show_file_list_command = "zip -sf #{package_file_path}"
+                       extract_file_list_command = "unzip -o \"#{package_file_path}\" -d \"#{path}\""
+               when ".tar" then
+                       # path should be unix path if it is used in tar command
+                       _package_file_path = Utils.get_unix_path(package_file_path)
+                       _path = Utils.get_unix_path(path)
+                       show_file_list_command = "tar -tf #{_package_file_path}"
+                       extract_file_list_command = "tar xf \"#{_package_file_path}\" -C \"#{_path}\""
+               else
+                       logger.error "\"#{filename}\" is not supported."
+                       return nil
+               end
+
+               system "#{show_file_list_command} > #{temp_pkg_file_list_path}"
+               File.open(pkg_file_list_path, "a+") do |targetfile|
+                       File.open(temp_pkg_file_list_path, "r") do |sourcefile|
+                               sourcefile.each_line do |l|
+                                       if l.strip.start_with? "data/" then
+                                               ml = l.strip[5..-1]
+                                               targetfile.puts ml
+                                       else next end
+                               end
+                       end
+               end
+               File.delete(temp_pkg_file_list_path)
+
+               case ext
+               when ".zip" then
+                       if Utils.is_windows_like_os( Utils::HOST_OS ) then
+                               log = unzip_file(package_file_path, path)
+                       else
+                               #result = Utils.execute_shell_return(extract_file_list_command)
+                               #if result.nil? then log = nil
+                               #else log = result.join("") end
+                               log = `#{extract_file_list_command}`
+                       end
+               when ".tar" then
+                       #result = Utils.execute_shell_return(extract_file_list_command)
+                       #if result.nil? then log = nil
+                       #else log = result.join("") end
+                       log = `#{extract_file_list_command}`
+               end
+
+               if log == "" then log = nil end
+               if log.nil? then
+                       logger.error "Failed to extract \"#{filename}\" file"
+                       logger.info "  [file: #{package_file_path}]"
+                       logger.info "  [from: #{path}]"
+                       logger.info "  [to: #{target_path}]"
+                       logger.info "  [cmd: #{extract_file_list_command}]"
+                       return nil
+               end
+
+               logger.info "Extracted \"#{filename}\" file.. OK"
+               log = log + "[file: #{package_file_path}]\n"
+               log = log + "[from: #{path}]\n"
+               log = log + "[to: #{target_path}]\n"
+               log = log + "[cmd: #{extract_file_list_command}]\n"
+               return log
+       end
+
+       def FileInstaller.extract_a_file(package_file_path, target_file, path, logger)
+               dirname = File.dirname(package_file_path)
+               filename = File.basename(package_file_path)
+               ext = File.extname(filename)
+
+               case ext
+               when ".zip" then
+                       if not path.nil? then
+                               extract_file_command = "unzip -x #{package_file_path} #{target_file} -d #{path}"
+                       else
+                               extract_file_command = "unzip -x #{package_file_path} #{target_file}"
+                       end
+               when ".tar" then
+                       # path should be unix path if it is used in tar command
+                       _package_file_path = Utils.get_unix_path(package_file_path)
+                       _path = Utils.get_unix_path(path)
+                       if not path.nil? then
+                               extract_file_command = "tar xf #{_package_file_path} -C #{_path} #{target_file}"
+                       else
+                               extract_file_command = "tar xf #{_package_file_path} #{target_file}"
+                       end
+               end
+
+               system "#{extract_file_command}"
+
+               if not path.nil? then
+                       target_file_path = File.join(path, target_file)
+               else
+                       target_file_path = target_file
+               end
+
+               if File.exist? target_file_path then
+                       logger.info "Extracted \"#{target_file}\" file.."
+                       return true
+               else
+                       logger.warn "Failed to extracted \"#{target_file}\" file.."
+                       logger.info "  [file: #{package_file_path}]"
+                       logger.info "  [path: #{path}]"
+                       logger.info "  [cmd: #{extract_file_command}]"
+                       return false
+               end
+       end
+
+       def FileInstaller.unzip_file(zipfile, dest)
+               log = ""
+               Zip::ZipFile.open(zipfile) do |zip_file|
+                       zip_file.each do |f|
+                               f_path = File.join(dest, f.name)
+                               FileUtils.mkdir_p(File.dirname(f_path))
+                               if File.exist?(f_path) then
+                                       log = log + "[Warn] Exist file : #{f_path}\n" unless f_path.end_with? "/"
+                               else
+                                       zip_file.extract(f, f_path)
+                                       if not f_path.end_with? "/" then
+                                               log = log + "[info] Extracted file : #{f_path}\n"
+                                       end
+                               end
+                       end
+               end
+               return log
+       end
+
+       def FileInstaller.unzip_a_file(zipfile, file, dest)
+               Zip::ZipFile.open(zipfile) do |zip_file|
+                       zip_file.each do |f|
+                               if f.name.strip == file then
+                                       f_path = File.join(dest, f.name)
+                                       FileUtils.mkdir_p(File.dirname(f_path))
+                                       zip_file.extract(f, f_path) unless File.exist?(f_path)
+                                       break
+                               end
+                       end
+               end
+       end
 end
-
index dce1b6b2d05619157a30fe15205835410d1a936b..e4902750d04864c689cf3426c98bab14849159e7 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- packageServer.rb 
+
+ packageServer.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -29,329 +29,345 @@ Contributors:
 require 'fileutils'
 $LOAD_PATH.unshift File.dirname(__FILE__)
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
+$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/build_server"
+require "BuildComm"
 require "packageServerLog"
-require "serverConfig"
+require "packageServerConfig"
 require "distribution"
+require "SocketRegisterListener"
 require "client"
 require "utils"
 require "mail"
+require "DistSync"
 
 class PackageServer
-       attr_accessor :id, :location
-    
+       attr_accessor :id, :location, :log, :integrity
+       attr_accessor :finish, :port
+       attr_accessor :incoming_path
+       attr_accessor :distribution_list
+       attr_accessor :sync_interval, :passwd
+
        # constant
-    SUPPORTED_OS = ["linux", "windows", "darwin"]
+       SERVER_ROOT = "#{PackageServerConfig::CONFIG_ROOT}/pkg_server"
+       DIBS_LOCK_FILE_PATH = "#{SERVER_ROOT}/.server_loc"
 
        # initialize
        def initialize (id)
-               @id = id
                @location = ""
                @distribution_list = []
                # distribution name -> server_url hash
                @dist_to_server_url = {}
-
-               if not File.exist? $server_root then
-                       FileUtils.mkdir_p( $server_root )
+               @integrity = "YES"
+               @auto_sync_flag = "NO"
+               @finish = false
+               @port = 3333
+               @test_time=0 #test time in mili-seconds
+               @lock_file= nil
+               @sync_interval = 3600
+               @passwd = ""
+
+               update_config_information(id)
+
+               if not File.exist?( SERVER_ROOT )
+                       FileUtils.mkdir_p( SERVER_ROOT )
                end
-               @log = PackageServerLog.new( "#{$server_root}/.#{@id}.log", $stdout) 
+               @log = PackageServerLog.new( @log_file_path )
 
                server_information_initialize()
-               set_distribution_list()
        end
 
        # create
-       def create (id, dist_name, server_url, loc = nil )
-               @id = id 
+       def create( id, dist_name, server_url, loc = nil )
+               update_config_information(id)
+
                if loc.nil? or loc.empty? then
-                       @location = Dir.pwd + "/" + id 
+                       @location = Dir.pwd + "/" + @id
                else
-                       if loc.end_with? "/" then  
-                               @location = loc + id 
-                       else 
-                               @location = loc + "/" + id 
+                       if Utils.is_absolute_path(loc) then
+                               @location = File.join(loc, @id)
+                       else
+                               @location = File.expand_path(File.join(Dir.pwd, loc, @id))
                        end
                end
 
+               # error check : check for already exist in server @id
+               if File.exist? @config_dir
+                       raise RuntimeError, "Server create fail. server id [#{@id}] is already exist"
+               end
+
+               # name check
+               if dist_name.strip.eql? "distribution.info" then
+                       raise RuntimeError, "id \"distribution.info\" is not available"
+               end
+
                # create locking file
-               File.open("#{$server_create_loc_file}", File::RDWR|File::CREAT, 0644) {|f|
-                       f.flock(File::LOCK_EX)
-                       f.rewind
-                       f.flush
-                       f.truncate(f.pos)
-
-                       # error check : check for already exist in server id 
-                       if File.exist? "#{$server_root}/#{id}" 
-                               raise RuntimeError, "Server create fail. server id [#{id}] is already exist"
-                       end
-                       
-                       # error check : check for already exist in server directory 
-                       if File.exist? "#{@location}/#{dist_name}"
-                               raise RuntimeError, "Server create fail. directory is already exist [#{@location}/#{dist_name}]" 
-                       end
-    
-                       # create server config directory
-                       FileUtils.mkdir_p "#{$server_root}/#{id}"
-                       FileUtils.mkdir_p "#{$server_root}/#{id}/incoming"
-
-                       if (not server_url.empty?) and (not Utils.is_url_remote(server_url))
-                               # if server_url is local server address then generate absoulte path 
-                               if not Utils.is_absolute_path( server_url ) then 
-                                       if server_url.end_with?("/") then
-                                               server_url = Utils::WORKING_DIR + server_url 
-                                       else
-                                               server_url = Utils::WORKING_DIR + "/" + server_url 
-                                       end
-                               end
-                       end 
+               lock_file = Utils.file_lock(DIBS_LOCK_FILE_PATH)
 
-                       # create server configure file
-                       File.open( "#{$server_root}/#{id}/config", "w" ) do |f|
-                               f.puts "location : #{@location}"
-                               f.puts "server_url : #{dist_name} ->  #{server_url}"
-                       end
-                       
-                       # create location's directory
-                       FileUtils.mkdir_p "#{@location}"
-                       
-                       create_distribution_struct( dist_name, server_url )
-               }       
+               # create server config directory
+               FileUtils.mkdir_p @config_dir
+               FileUtils.mkdir_p @incoming_path
+
+               if (not server_url.empty?) and \
+                       (not Utils.is_url_remote(server_url)) and \
+                       (not Utils.is_absolute_path(server_url)) then
+                       # if server_url is local server address then generate absoulte path
+                       server_url = File.join(Utils::WORKING_DIR, server_url)
+               end
+
+               # create server configure file
+               File.open( @config_file_path, "w" ) do |f|
+                       f.puts "location : #{@location}"
+                       f.puts "integrity check : #{@integrity}"
+                       f.puts "auto sync : #{@auto_sync_flag}"
+                       f.puts "sync interval : #{@sync_interval}"
+                       f.puts "server_url : #{dist_name} ->  #{server_url}"
+               end
+
+               # create location's directory
+               FileUtils.mkdir_p "#{@location}"
+
+               create_distribution_struct( dist_name, server_url )
+               Utils.file_unlock(lock_file)
+
+               @log.output( "package server [#{@id}] created successfully", Log::LV_USER )
        end
 
-       def register( source_pkg_file_path_list, binary_pkg_file_path_list, dist_name, snapshot, test )
+       def register( file_path_list, dist_name, snapshot, test_flag, internal_flag = false )
                @log.info "package register in server"
-               if dist_name.empty? then dist_name = get_default_dist_name() end
-               if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end
                distribution = get_distribution( dist_name )
 
-               # distribution lock 
-               File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f|
-                       f.flock(File::LOCK_EX)
-                       f.rewind
-                       f.flush
-                       f.truncate(f.pos)
-               
-                       source_pkg_file_name_list = [] 
-                       updated_os_list = []
-                       append_pkg_list = []
-                       used_source_pkg_list = []
-                       package_list = []
-
-                       # error check 
-            source_pkg_file_path_list.each do |l| 
-                               # error check for file exist 
-                if not File.exist? l
-                                       raise RuntimeError, "source package file does not exist [#{l}]"
-                               end 
-
-                               source_pkg_file_name_list.push File.basename( l )
-                       end     
-            binary_pkg_file_path_list.each do |l| 
-                               # error check for file exist 
-                if not File.exist? l
-                                       raise RuntimeError, "binary package file does not exist [#{l}]"
-                               end 
-                       end     
-
-                       # register binary package
-            binary_pkg_file_path_list.each do |l| 
-                               # get package class using bianry file 
-                               pkg = distribution.get_package_from_file(l) 
-
-                               if pkg.nil? or pkg.package_name.empty? then
-                                       raise "[#{l}]'s pkginfo.manifest file is incomplete."
-                               end 
-                               package_list.push pkg
-
-                               if test then
-                                       if not pkg.source.empty? then   
-                                               if not source_pkg_file_name_list.include? "#{pkg.source}_#{pkg.version}.tar.gz"
-                                                       raise "binary package and source package must be upload same time"
-                                               end
-                                               
-                                               pkg.src_path = "/temp/#{pkg.source}_#{pkg.version}.tar.gz"
-                                       end
-                                       pkg = distribution.register_for_test(l ,pkg )
+               # distribution lock
+               @lock_file = Utils.file_lock(distribution.lock_file_path)
+
+               updated_os_list = []
+               registed_package_list = []
+               binary_pkg_file_path_list = []
+               link_pkg_file_path_list = []
+               archive_pkg_file_path_list = []
+               snapshot_name = ""
+
+               file_path_list.each do |f|
+                       # error check for file exist
+                       if not File.exist? f
+                               raise RuntimeError, "package file does not exist [#{f}]"
+                       end
+
+                       pkg = distribution.get_package_from_file(f)
+
+                       # binary package
+                       if not pkg.nil? then
+
+                               # find link package
+                               pkg_os = Utils.get_os_from_package_file(f)
+                               link_pkg = distribution.get_link_package(pkg, pkg_os)
+                               if link_pkg.nil? then
+                                       binary_pkg_file_path_list.push f
                                else
-                                       if pkg.package_name.empty? or pkg.version.empty? or pkg.os.empty? or pkg.maintainer.empty? then
-                                               raise "[#{l}]'s pkginfo.manifest file is incomplete."
-                                       # binary only package
-                                       elsif pkg.attribute.include? "binary" then
-                                               @log.info "binary package [#{l}] is binary only package"
-                                               pkg.src_path = ""
-                                       elsif pkg.source.empty? then
-                                               raise "[#{l}]'s pkginfo.manifest file is incomplete." 
-                                       # binary package
-                                       else 
-                                               if not source_pkg_file_name_list.include? "#{pkg.source}_#{pkg.version}.tar.gz"
-                                                       raise "binary package [#{pkg.package_name}]'s source package must be upload same time"
-                                               end
-                                                       
-                                               @log.info "binary package [#{l}]'s source package is #{pkg.source}" 
-                                               used_source_pkg_list.push "#{pkg.source}_#{pkg.version}.tar.gz"
-                                               pkg.src_path = "/source/#{pkg.source}_#{pkg.version}.tar.gz"
-                                       end
-           
-                                       pkg = distribution.register(l ,pkg )
-                                       updated_os_list.push pkg.os 
+                                       link_pkg_file_path_list.push [link_pkg.path, File.basename(f)]
+                                       pkg.checksum = link_pkg.checksum
+                                       pkg.size = link_pkg.size
                                end
-                                       
-                               append_pkg_list.push pkg
-                       end 
-
-                       # check install dependency integrity
-                       if not test then distribution.check_instll_dependency_integrity end
-               
-                       source_pkg_file_path_list.each do |source_path|
-                               source_name = File.basename(source_path)
-                               if File.exist? "#{@location}/#{dist_name}/source/#{source_name}" then
-                                       @log.warn "source package already exist then does not register"
-                                       next
-                               end 
-
-                               if test then
-                                       @log.info "source package [#{source_name}] register in temp/]"
-                                       FileUtils.cp( source_path, "#{@location}/#{dist_name}/temp/" )
+
+                               # update os information
+                               if pkg.os_list.include? pkg_os then
+                                       pkg.os = pkg_os
+                                       pkg.os_list = [pkg_os]
                                else
-                                       @log.info "source package [#{source_name}] register in source/]"
-                                       FileUtils.cp( source_path, "#{@location}/#{dist_name}/source/" )
+                                       raise RuntimeError, "package file name is incorrect [#{f}]"
                                end
-                       end 
 
-                       # register archive pakcage list. 
-                       distribution.write_archive_pkg_list( source_pkg_file_name_list - used_source_pkg_list )
+                               updated_pkg = register_package(distribution, pkg, f, test_flag, internal_flag)
 
-            binary_pkg_file_path_list.each do |l| 
-                               if test then 
-                                       FileUtils.cp( l, "#{@location}/#{dist_name}/temp/" )
-                               else 
-                                       FileUtils.cp( l, "#{@location}/#{dist_name}/binary/" )
+                               updated_os_list.push updated_pkg.os
+                               registed_package_list.push updated_pkg
+                               # archive package
+                       else
+                               if test_flag then
+                                       @log.error("archive package does not using test mode", Log::LV_USER)
+                                       return
                                end
+
+                               file_name = File.basename(f)
+                               distribution.register_archive_pkg(file_name)
+                               archive_pkg_file_path_list.push f
                        end
+               end
+
+               # check install dependency integrity
+               if not test_flag and @integrity.eql? "YES" then
+                       registed_package_list.each do |pkg|
+                               distribution.check_package_integrity(pkg)
+                       end
+               end
+
+               # move file to package server
+               binary_pkg_file_path_list.each do |l|
+                       if test_flag then
+                               FileUtils.copy_file( l, "#{distribution.location}/temp/#{File.basename(l)}" )
+                       else
+                               FileUtils.copy_file( l, "#{distribution.location}/binary/#{File.basename(l)}" )
+                       end
+               end
+
+               # link to package server
+               link_pkg_file_path_list.each do |l|
+                       if test_flag then
+                               src_file = File.join(distribution.location, l[0])
+                               dest_file = File.join(distribution.location, "temp", l[1])
+                               FileUtils.ln( src_file, dest_file, :force => true )
+                       else
+                               src_file = File.join(distribution.location, l[0])
+                               dest_file = File.join(distribution.location, "binary", l[1])
+                               FileUtils.ln( src_file, dest_file, :force => true )
+                       end
+               end
+
+               archive_pkg_file_path_list.each do |l|
+                       FileUtils.mv( l, "#{distribution.location}/source/" )
+               end
 
-                       # write package list for updated os
-                       updated_os_list.uniq!
-                       updated_os_list.each do |os|
-               distribution.write_pkg_list( os ) 
+               # write package list for updated os
+               updated_os_list.uniq!
+               updated_os_list.each do |os|
+                       distribution.write_pkg_list(os)
+               end
+
+               # register archive pakcage list.
+               distribution.write_archive_pkg_list()
+
+               # send email
+               if test_flag then
+                       msg_list = []
+
+                       registed_package_list.each do  |p|
+                               msg_list.push("%-30s: %08s" % [ p.package_name.strip, p.version.strip ] )
                        end
+                       # email just remote package server
+                       # Mail.send_package_registe_mail( msg_list, @id )
+               end
+
+               # if snapshot mode is true then generate snapshot
+               if snapshot or test_flag then
+                       @log.info "generaging snapshot"
+                       snapshot_name = distribution.generate_snapshot("", "", false, "Changed package: \n" + registed_package_list.map{|x|"- #{x.package_name}"}.join("\n") + "\n\n" + get_changelog_string(registed_package_list) )
+               end
 
-            # if snapshot mode is true then generate snapshot 
-            if snapshot or test then
-                               @log.info "generaging snapshot"
-                distribution.generate_snapshot("", "", "")
-                       end 
-
-                       # send email
-                       if not test then 
-                               msg_list = []
-
-                               package_list.map{ |p| 
-                                               msg_list.push("%-30s: %08s" % [ p.package_name.strip, p.version.strip ] )
-                               } 
-                               # email just remote package server
-                               # Mail.send_package_registe_mail( msg_list, @id )  
+               Utils.file_unlock(@lock_file)
+               @log.output( "package registed successfully", Log::LV_USER)
+
+               return snapshot_name
+       end
+
+       def get_changelog_string( package_list )
+               log_list = {}
+               package_list.each do |pkg|
+                       if not pkg.does_change_exist? then next end
+                       set = false
+                       if log_list[[pkg.package_name, pkg.version, pkg.get_changes]].nil? then
+                               log_list[[pkg.package_name, pkg.version, pkg.get_changes]] = pkg.os_list
+                       else
+                               log_list[[pkg.package_name, pkg.version, pkg.get_changes]] = log_list[[pkg.package_name, pkg.version, pkg.get_changes]] + pkg.os_list
                        end
-        }
-    end
+               end
+               str=""
+               log_list.each do |key, os_list|
+                       str = str + "Package: #{key[0]}\nOS: #{os_list.join(", ")}\nVersion: #{key[1]}\nChanges: \n#{key[2].sub(/^==/,'Uploader:')}\n\n"
+               end
+               return str
+       end
 
-       def generate_snapshot( snpashot_name, dist_name, base_snapshot, binary_pkg_file_path_list)
+       def generate_snapshot( snpashot_name, dist_name, base_snapshot )
                @log.info "generating snapshot"
-               if dist_name.empty? then dist_name = get_default_dist_name() end
-               if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end
                distribution = get_distribution( dist_name )
 
-               File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f|
-                       f.flock(File::LOCK_EX)
-                       f.rewind
-                       f.flush
-                       f.truncate(f.pos)
-                       
-                       append_pkg_list = []
-            binary_pkg_file_path_list.each do |l| 
-                               if not File.exist? l then raise RuntimeError,"Can't find binary package file [#{l}]" end
-                               pkg = distribution.get_package_from_file(l)
-                               if l.start_with? "/" 
-                                       pkg.path = "#{l}"
-                               else
-                                       pkg.path = "#{Dir.pwd}/#{l}"
-                               end
-                               append_pkg_list.push pkg
-            end 
-                       
-                       distribution.generate_snapshot( snpashot_name, base_snapshot, append_pkg_list)
-               }
+               @lock_file = Utils.file_lock(distribution.lock_file_path)
+
+               snapshot_name = distribution.generate_snapshot( snpashot_name, base_snapshot, true, "SYSTEM:")
+
+               Utils.file_unlock(@lock_file)
+
+               return snapshot_name
        end
 
-       def sync( dist_name, mode )
+       def sync( dist_name, mode, snapshot = "" )
                @log.info "sync from server"
-               if dist_name.empty? then dist_name = get_default_dist_name() end
-               if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end
-               distribution = get_distribution( dist_name ) 
-       
-               if distribution.server_url.empty? then 
-                       @log.error( "This distribution has not remote server", Log::LV_USER) 
+               distribution = get_distribution( dist_name )
+
+               if distribution.server_url.empty? then
+                       @log.error( "This distribution has not remote server", Log::LV_USER)
                        return
-               end 
-
-               File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f|
-                       f.flock(File::LOCK_EX)
-                       f.rewind
-                       f.flush
-                       f.truncate(f.pos)
-            
-                       distribution.sync( mode, "linux" )
-                       distribution.sync( mode, "windows" )
-                       distribution.sync( mode, "darwin" )
-                       distribution.sync_archive_pkg
-               }
+               end
+
+               begin
+                       ret = distribution.sync(mode, snapshot)
+
+                       if ret then
+                               distribution.generate_snapshot("", "", false, distribution.last_sync_changes)
+                       end
+    
+                       @log.output( "package server [#{@id}]'s distribution [#{dist_name}] has been synchronized.", Log::LV_USER )
+               rescue => e
+                       @log.error( e.message, Log::LV_USER)
+               end
        end
 
        def add_distribution( dist_name, server_url, clone )
-               File.open("#{$server_create_loc_file}", File::RDWR|File::CREAT, 0644) {|f|
-                       f.flock(File::LOCK_EX)
-                       f.rewind
-                       f.flush
-                       f.truncate(f.pos)
-
-                       # error check : check for already exist in server directory 
-                       if @dist_to_server_url.keys.include? dist_name.strip then
-                               raise RuntimeError, "distribution already exist : #{dist_name}"
-                       end
-                       if File.exist? "#{@location}/#{dist_name}"
-                               raise RuntimeError, "distribution directory already exist [#{@location}/#{dist_name}]" 
-                       end
-            
-                       if (not server_url.empty?) and (not Utils.is_url_remote(server_url))
-                               # if server_url is local server address then generate absoulte path 
-                               if not Utils.is_absolute_path( server_url ) then 
-                                       if server_url.end_with?("/") then
-                                               server_url = Utils::WORKING_DIR + server_url 
-                                       else
-                                               server_url = Utils::WORKING_DIR + "/" + server_url 
-                                       end
-                               end
-                       end 
+               lock_file = Utils.file_lock(@server_lock_file_path)
 
-                       File.open( "#{$server_root}/#{@id}/config", "a" ) do |f|
-                               if clone then 
-                                       @log.info "add distribution using [#{server_url}] in clone mode"
-                                       f.puts "server_url : #{dist_name} ->  "
+               # error check : check for already exist in server directory
+               if @dist_to_server_url.keys.include? dist_name.strip then
+                       Utils.file_unlock(@lock_file)
+                       raise RuntimeError, "distribution already exist : #{dist_name}"
+               end
+
+               # name check
+               if dist_name.strip.eql? "distribution.info" then
+                       Utils.file_unlock(@lock_file)
+                       raise RuntimeError, "id \"distribution.info\" is not available"
+               end
+
+               # modify server url
+               if (not server_url.empty?) and (not Utils.is_url_remote(server_url))
+                       # if server_url is local server address then generate absoulte path
+                       if not Utils.is_absolute_path( server_url ) then
+                               if server_url.end_with?("/") then
+                                       server_url = Utils::WORKING_DIR + server_url
                                else
-                                       @log.info "add distribution using [#{server_url}]"
-                                       f.puts "server_url : #{dist_name} ->  #{server_url}"
+                                       server_url = Utils::WORKING_DIR + "/" + server_url
                                end
                        end
-                       
-                       create_distribution_struct( dist_name, server_url )
-               }
+               end
+
+               add_dist_for_config_file(dist_name, server_url, clone)
+               create_distribution_struct( dist_name, server_url )
+
+               Utils.file_unlock(lock_file)
+               @log.output( "distribution [#{dist_name}] added successfully", Log::LV_USER )
        end
 
-       def remove_server( id )
-               @log.info( "Package server [#{id}] will be removed and all server information delete", Log::LV_USER)
+       def add_os(dist_name, os)
+               dist = get_distribution(dist_name)
 
-               if File.exist? "#{$server_root}/#{id}/config" then
-                       File.open "#{$server_root}/#{id}/config" do |f|
+               # distribution lock
+               @lock_file = Utils.file_lock(dist.lock_file_path)
+
+               dist.add_os(os)
+
+               @log.info "generaging snapshot"
+               dist.generate_snapshot("", "", false, "Add #{os} Package server")
+
+               Utils.file_unlock(@lock_file)
+               @log.output( "package server add os [#{os}] successfully", Log::LV_USER )
+       end
+
+       def remove_server()
+               @log.info( "Package server [#{@id}] will be removed and all server information delete", Log::LV_USER)
+
+               lock_file = Utils.file_lock(DIBS_LOCK_FILE_PATH)
+               if File.exist? @config_file_path then
+                       File.open @config_file_path do |f|
                                f.each_line do |l|
-                                       if l.start_with?( "location : ") then 
+                                       if l.start_with?( "location : ") then
                                                location= l.split(" : ")[1]
                                                FileUtils.rm_rf l.split(" : ")[1].strip
                                                @log.info( "server location removed : #{location}", Log::LV_USER)
@@ -359,91 +375,245 @@ class PackageServer
                                end
                        end
                else
-                       @log.error( "Can't find server information : #{id}", Log::LV_USER)
-               end 
-               
-               FileUtils.rm_rf "#{$server_root}/.#{id}.log"
-               FileUtils.rm_rf "#{$server_root}/#{id}"
+                       @log.error( "Can't find server information : #{@id}", Log::LV_USER)
+               end
+
+               FileUtils.rm_rf @config_dir
+               FileUtils.rm_rf @log_file_path
+
+               Utils.file_unlock(lock_file)
+               @log.output( "package server [#{@id}] removed successfully", Log::LV_USER )
        end
 
-       def remove_pkg( id, dist_name, pkg_name_list )
+       def remove_dist( dist_name )
+               @log.info "remove distribution in server"
+               distribution = get_distribution( dist_name )
+
+               lock_file = Utils.file_lock(@server_lock_file_path)
+
+               # modify config file
+               config_file = File.readlines(@config_file_path)
+               File.open(@config_file_path, 'w') do |f|
+                       config_file.each do  |line|
+                               f.puts(line) if not line =~ /server_url : #{dist_name} ->/
+                       end
+               end
+
+               # modify info file
+               config_file = File.readlines("#{@location}/distribution.info")
+               File.open("#{@location}/distribution.info", 'w') do |f|
+                       remove_flag = false
+                       config_file.each do  |line|
+                               if line.start_with? "name :" then
+                                       if line.split(':')[1].strip.eql? dist_name then
+                                               remove_flag = true
+                                       else
+                                               remove_flag = false
+                                       end
+
+                               end
+
+                               # rewrite information for not remove distribution
+                               if not remove_flag then
+                                       f.puts line
+                               end
+                       end
+               end
+
+               # remove distribution directory
+               FileUtils.rm_rf distribution.location
+
+               # remove distribution struct
+               @distribution_list.delete distribution
+
+               Utils.file_unlock(lock_file)
+       end
+
+       def remove_pkg( dist_name, pkg_name_list, os )
                @log.info "package remove in server"
-               if dist_name.empty? then dist_name = get_default_dist_name() end
-               if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end
                distribution = get_distribution( dist_name )
 
-               # distribution lock 
-               File.open("#{@location}/#{dist_name}/.lock_file", File::RDWR|File::CREAT, 0644) {|f|
-                       f.flock(File::LOCK_EX)
-                       f.rewind
-                       f.flush
-                       f.truncate(f.pos) 
+               lock_file = Utils.file_lock(@server_lock_file_path)
+
+               distribution.remove_pkg(pkg_name_list, os)
 
-                       distribution.remove_pkg(pkg_name_list)
-               }
+               # generate snapshot
+               @log.info "generaging snapshot"
+               distribution.generate_snapshot("", "", false, "SYSTEM: Package \"#{pkg_name_list.join(", ")}\" is(are) removed in #{os} server")
+
+               Utils.file_unlock(lock_file)
+               @log.output( "package removed successfully", Log::LV_USER )
        end
 
-       def find_source_package_path( dist_name, pkg_file_name_list ) 
-               if dist_name.empty? then dist_name = get_default_dist_name() end
-               if dist_name.empty? then raise RuntimeError,"Can't find distribution information" end
+       def remove_snapshot( dist_name, snapshot_list )
+               @log.info "remove snapshot in server"
                distribution = get_distribution( dist_name )
 
-               pkg_file_name_list.each do |pkg|
-                       pkg_path = "#{@location}/#{dist_name}/source/#{pkg}"
-                       if File.exist? pkg_path then
-                               @log.info( "#{pkg}", Log::LV_USER)
+               lock_file = Utils.file_lock(@server_lock_file_path)
+
+               distribution.remove_snapshot(snapshot_list)
+
+               Utils.file_unlock(lock_file)
+       end
+
+       def clean( dist_name, snapshot_list )
+               @log.info "pakcage server clean"
+               distribution = get_distribution( dist_name )
+
+               lock_file = Utils.file_lock(@server_lock_file_path)
+
+               distribution.clean( snapshot_list )
+
+               # remove incoming dir
+               FileUtils.rm_rf incoming_path
+               FileUtils.mkdir incoming_path
+
+               Utils.file_unlock(lock_file)
+       end
+
+       # start server daemon
+       def start( port, passwd )
+               @log.info "Package server Start..."
+               # set port number. default port is 3333
+               @port = port
+
+               # set job request listener
+               @log.info "Setting listener..."
+               listener = SocketRegisterListener.new(self)
+               listener.start
+
+               # set auto sync
+               if @auto_sync_flag.eql? "YES" then
+                       @log.info "Setting auto sync..."
+                       autosync = DistSync.new(self)
+                       autosync.start
+               end
+
+               # set password
+               @passwd = passwd
+
+               # main loop
+               @log.info "Entering main loop..."
+               if @test_time > 0 then start_time = Time.now end
+               while( not @finish )
+                       # sleep
+                       if @test_time > 0 then
+                               curr_time = Time.now
+                               if (curr_time - start_time).to_i > @test_time then
+                                       puts "Test time is elapsed!"
+                                       break
+                               end
                        else
-                               @log.error( "Can't find [#{pkg}] in source package", Log::LV_USER)
+                               sleep 1
                        end
-               end 
+               end
        end
 
-       def PackageServer.list_id  
-               @@log = PackageServerLog.new( "#{$server_root}/.log", $stdout) 
+       # stop server daemon
+       def stop( port, passwd )
+               # set port number. default port is 3333
+               @port = port
+               @finish = false
 
-               d = Dir.new( $server_root )
-               s = d.select {|f| not f.start_with?(".") }  
+               client = BuildCommClient.create("127.0.0.1", @port, @log)
+               if client.nil? then
+                       raise RuntimeError, "Server does not listen in #{@port} port"
+               end
+
+               client.send("STOP|#{passwd}")
+
+               ret = client.receive_data
+               if not ret.nil? and ret[0].strip.eql? "SUCC" then
+                       @log.output( "Package server is stopped", Log::LV_USER)
+               else
+                       @log.output( "Package server return error message! #{ret}", Log::LV_USER)
+                       if not client.get_error_msg().empty? then
+                               @log.output( "Error: #{client.get_error_msg()}", Log::LV_USER)
+                       end
+               end
+               client.terminate
+
+       end
+
+       def self.list_id
+               @@log = PackageServerLog.new("#{SERVER_ROOT}/.log")
+
+               d = Dir.new( SERVER_ROOT )
+               s = d.select {|f| not f.start_with?(".") }
                s.sort!
-       
+               server_list = []
+
                @@log.output( "=== server ID list ===", Log::LV_USER)
                s.each do |id|
+                       if File.basename(id).include?(".log") then next end
+
+                       server_list.push id
                        @@log.output( id, Log::LV_USER)
-               end 
+               end
+               @@log.close
+               FileUtils.rm_rf("#{SERVER_ROOT}/.log")
+
+               return server_list
        end
 
-       def PackageServer.list_dist( id )
-               @@log = PackageServerLog.new( "#{$server_root}/.log", $stdout) 
-               
+       def self.list_dist( id )
+               @@log = PackageServerLog.new( "#{SERVER_ROOT}/.log" )
+
                @@log.output( "=== ID [#{id}]'s distribution list ===", Log::LV_USER)
 
+               dist_list = []
+
                # read package id information
-               if File.exist? "#{$server_root}/#{id}/config" then
-                       File.open "#{$server_root}/#{id}/config" do |f|
-                               f.each_line do |l|
-                                       if l.start_with?( "server_url : ") and l.include?( "->" ) then
-                                               @@log.output( l.split(" : ")[1].split("->")[0], Log::LV_USER)
-                                       end
+               config_file_path = "#{SERVER_ROOT}/#{id}/config"
+               if not File.exist? config_file_path
+                       raise RuntimeError, "[#{id}] is not server ID"
+               end
+
+               File.open config_file_path do |f|
+                       f.each_line do |l|
+                               if l.start_with?( "server_url : ") and l.include?( "->" ) then
+                                       dist_name = l.split(" : ")[1].split("->")[0]
+
+                                       dist_list.push dist_name
+                                       @@log.output( dist_name, Log::LV_USER)
                                end
                        end
-               else
-                       raise RuntimeError, "[#{id}] is not server ID"
-               end 
+               end
+               @@log.close
+               FileUtils.rm_rf("#{SERVER_ROOT}/.log")
+
+               return dist_list
        end
 
-       def get_default_dist_name() 
-               if @distribution_list.empty? then 
+       def get_default_dist_name()
+               if @distribution_list.empty? then
                        raise RuntimeError,"Server [#{@id}] does not have distribution"
-               end 
-               return @distribution_list[0].name 
+               end
+               return @distribution_list[0].name
+       end
+
+       def reload_dist_package()
+               # create locking file
+               lock_file = Utils.file_lock(@server_lock_file_path)
+               @distribution_list.each do |dist|
+                       dist.initialize_pkg_list
+               end
+               Utils.file_unlock(lock_file)
+       end
+
+       def release_lock_file
+               if not @lock_file.nil? then
+                       Utils.file_unlock(@lock_file)
+               end
        end
 
        # PRIVATE METHODS/VARIABLES
-       private 
+       private
 
-       def server_information_initialize 
+       def server_information_initialize
                # if id is nil or empty then find default id
-               if @id.nil? or @id.empty? 
-                       d = Dir.new( $server_root )
+               if @id.nil? or @id.empty?
+                       d = Dir.new( SERVER_ROOT )
                        s = d.select {|f| not f.start_with?(".") }
                        if s.length.eql? 1 then
                                @log.info "using default server ID [#{s[0]}]"
@@ -454,32 +624,43 @@ class PackageServer
                end
 
                # read package id information
-               if File.exist? $server_root and File.exist? "#{$server_root}/#{@id}/config" then
-                       File.open "#{$server_root}/#{@id}/config" do |f|
+               if File.exist? @config_file_path
+                       File.open @config_file_path do |f|
                                f.each_line do |l|
-                                       if l.start_with?( "location : ") then 
-                                               @location = l.split(" : ")[1].strip
-                                       elsif l.start_with?( "server_url : " ) then
-                                               info = l.split(" : ")[1].split("->")
-                                               @dist_to_server_url[info[0].strip] = info[1].strip 
+                                       if l.start_with?( "location :") then
+                                               @location = l.split(" :")[1].strip
+                                       elsif l.start_with?( "integrity check :") then
+                                               @integrity = l.split(" :")[1].strip.upcase
+                                       elsif l.start_with?( "auto sync :" ) then
+                                               @auto_sync_flag = l.split(" :")[1].strip.upcase
+                                       elsif l.start_with?( "sync interval :" ) then
+                                               @sync_interval = l.split(" :")[1].strip.to_i
+                                       elsif l.start_with?( "server_url :" ) then
+                                               info = l.split(" :")[1].split("->")
+                                               @dist_to_server_url[info[0].strip] = info[1].strip
                                        else
                                                @log.error "server config file has invalid information [#{l}]"
                                        end
                                end
                        end
-               end
-       end
 
-       def set_distribution_list
-               @dist_to_server_url.each do |dist_name, server_url|
-                       @distribution_list.push Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url,  @log)
+                       @dist_to_server_url.each do |dist_name, server_url|
+                               @distribution_list.push Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, self )
+                       end
                end
        end
 
        def get_distribution( dist_name )
+               if dist_name.nil? or dist_name.empty? then
+                       dist_name = get_default_dist_name()
+               end
+               if dist_name.empty? then
+                       raise RuntimeError,"Can't find distribution information"
+               end
+
                @distribution_list.each do |dist|
                        if dist.name.eql? dist_name.strip
-                               return dist 
+                               return dist
                        end
                end
 
@@ -487,40 +668,91 @@ class PackageServer
        end
 
        def create_distribution_struct( dist_name, server_url )
+               if File.exist? "#{@location}/#{dist_name}"
+                       raise RuntimeError, "distribution directory already exist [#{@location}/#{dist_name}]"
+               end
+
                FileUtils.mkdir "#{@location}/#{dist_name}"
                FileUtils.mkdir "#{@location}/#{dist_name}/binary"
                FileUtils.mkdir "#{@location}/#{dist_name}/source"
                FileUtils.mkdir "#{@location}/#{dist_name}/temp"
                FileUtils.mkdir "#{@location}/#{dist_name}/snapshots"
-           
+               File.open("#{@location}/#{dist_name}/#{Distribution::SNAPSHOT_INFO_FILE}", "w") {}
+               File.open("#{@location}/#{dist_name}/#{Distribution::OS_INFO_FILE}", "w") {}
+               File.open("#{@location}/#{dist_name}/#{Distribution::ARCHIVE_PKG_FILE}", "w") {}
+
                # generate distribution
-               distribution = Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, @log )
+               distribution = Distribution.new( dist_name, "#{@location}/#{dist_name}", server_url, self )
 
                # add dist
                @distribution_list.push distribution
-       
+
                if not server_url.empty?  then
                        @log.info "generate package server using remote package server [#{server_url}]"
 
-                       if Utils.is_url_remote(server_url) then  
+                       if Utils.is_url_remote(server_url) then
                                @log.info "[#{dist_name}] distribution creation. using remote server [#{server_url}]"
-                       else 
+                       else
                                @log.info "[#{dist_name}] distribution creation. using local server [#{server_url}]"
                        end
 
-                       distribution.sync( false, "linux" )
-                       distribution.sync( false, "windows" )
-                       distribution.sync( false, "darwin" )
-                       distribution.sync_archive_pkg
+                       distribution.sync(false)
+                       distribution.generate_snapshot("", "", false, distribution.last_sync_changes)
                else
                        @log.info "generate package server do not using remote package server"
-       
+
                        # write_pkg_list for empty file
-                       distribution.write_pkg_list( "linux" )
-                       distribution.write_pkg_list( "windows" )
-                       distribution.write_pkg_list( "darwin" ) 
-                       distribution.write_archive_pkg_list( "" )
+                       distribution.write_pkg_list(nil)
+                       distribution.write_archive_pkg_list()
+               end
+
+               # add dist information to distribution.info file
+               File.open("#{@location}/distribution.info", "a") do |f|
+                       f.puts "name : #{dist_name}"
+                       f.puts "time : #{Time.now.strftime("%Y%m%d%H%M%S")}"
+                       f.puts
                end
        end
-end
 
+       def register_package(distribution, pkg, file_path, test_flag, internal_flag)
+               # get package class using bianry file
+               if pkg.nil? or pkg.package_name.empty? then
+                       raise "[#{file_path}]'s pkginfo.manifest file is incomplete."
+               end
+
+               if not test_flag then
+                       # error check
+                       if pkg.package_name.empty? or pkg.version.empty? \
+                               or pkg.os.empty? or pkg.maintainer.empty? then
+                               raise "[#{file_path}]'s pkginfo.manifest file is incomplete."
+                       end
+
+                       updated_pkg = distribution.register(file_path, pkg, internal_flag )
+               else
+                       updated_pkg = distribution.register_for_test(file_path, pkg )
+               end
+
+               return updated_pkg
+       end
+
+       def add_dist_for_config_file(dist_name, server_url, clone)
+               File.open( @config_file_path, "a" ) do |f|
+                       if clone then
+                               @log.info "add distribution using [#{server_url}] in clone mode"
+                               f.puts "server_url : #{dist_name} ->  "
+                       else
+                               @log.info "add distribution using [#{server_url}]"
+                               f.puts "server_url : #{dist_name} ->  #{server_url}"
+                       end
+               end
+       end
+
+       def update_config_information(id)
+               @id = id
+               @config_dir = "#{SERVER_ROOT}/#{@id}"
+               @log_file_path = "#{SERVER_ROOT}/#{@id}.log"
+               @config_file_path = "#{@config_dir}/config"
+               @incoming_path = "#{@config_dir}/incoming"
+               @server_lock_file_path = "#{@config_dir}/.server_lock"
+       end
+end
diff --git a/src/pkg_server/packageServerConfig.rb b/src/pkg_server/packageServerConfig.rb
new file mode 100644 (file)
index 0000000..3c782a6
--- /dev/null
@@ -0,0 +1,34 @@
+=begin
+
+ serverConfig.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.dirname(__FILE__))+"/common"
+require "utils"
+
+class PackageServerConfig
+       CONFIG_ROOT = "#{Utils::HOME}/.build_tools"
+end
index b20c7985cdae218077ab9eb8606b5abf307c9b3e..1ca1068291c799f5ebd170a0b7d30c970d9ddf04 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- packageServerLog.rb 
+
+ packageServerLog.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -32,15 +32,15 @@ require "logger"
 
 class PackageServerLog < Log
 
-       def initialize(path, stream_out)
+       def initialize(path)
                super(path)
-               @extra_out = stream_out
+               @second_out = $stdout
        end
 
        protected
        def output_extra(msg)
-               @extra_out.puts msg
-       end     
+               @second_out.puts msg
+       end
 
 
 end
index bdacd822c1fdde9fd646bff10c8c71c90be1a770..f37d68bd9e6e958d84342e574e4f0b08479b1fcd 100644 (file)
@@ -1,6 +1,6 @@
 =begin
- serverOptParser.rb 
+
+ serverOptParser.rb
 
 Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 
@@ -30,171 +30,224 @@ require 'optparse'
 $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common"
 require "utils"
 
-def set_default( options ) 
-       if options[:id].nil? then options[:id] = "" end
-       if options[:dist].nil? then options[:dist] = "" end
-       if options[:url].nil? then options[:url] = "" end
-       if options[:os].nil? then options[:os] = "all" end
-       if options[:bpkgs].nil? then options[:bpkgs] = [] end
-       if options[:apkgs].nil? then options[:apkgs] = [] end
-       if options[:spkgs].nil? then options[:spkgs] = [] end
-       if options[:snap].nil? then options[:snap] = "" end
-       if options[:bsnap].nil? then options[:bsnap] = "" end
-       if options[:gensnap].nil? then options[:gensnap] = false end
-       if options[:force].nil? then options[:force] = false end
-       if options[:test].nil? then options[:test] = false end
-       if options[:clone].nil? then options[:clone] = false end
+def set_default( options )
+       options[:id] = ""
+       options[:dist] = ""
+       options[:url] = ""
+       options[:os] = "all"
+       options[:pkgs] = []
+       options[:snaps] = []
+       options[:bsnap] = ""
+       options[:port] = "3333"
+       options[:gensnap] = true
+       options[:force] = false
+       options[:test] = false
+       options[:clone] = false
+       options[:origin_pkg_name] = ""
+       options[:origin_pkg_os] = ""
+       options[:passwd] = ""
 end
 
 def option_error_check( options )
-               
-       case options[:cmd] 
-       when "create" 
-           if  options[:id].empty? or options[:dist].empty? then
-                       raise ArgumentError, "Usage: pkg-svr create -i <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> " + "\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> "
+
+       case options[:cmd]
+       when "create"
+               if      options[:id].empty? or options[:dist].empty? then
+                       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
-               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
-                       raise ArgumentError, "Usage: pkg-svr add-dist -i <id> -d <distribution> [-u <remote_server_url>] [-c] "
+               if      options[:id].empty? or options[:dist].empty? then
+                       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"
-           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
-       when "remove"
        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 "clean"
        else
-               raise ArgumentError, "input option incorrect : #{options[:cmd]}"
+               raise ArgumentError, "Input is incorrect : #{options[:cmd]}"
        end
 end
 
-def option_parse 
-    options = {}
-    banner = "Usage: pkg-svr {create|register|gen-snapshot|sync|add-dist|spkg-path|remove|remove-pkg|list|help} ..." + "\n" \
-        + "\t" + "pkg-svr create -i <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> " + "\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|
-        # Set a banner, displayed at the top
-        # of the help screen.
-
-               opts.banner = banner 
-
-        opts.on( '-i', '--id <id>', 'package server id' ) do|name|
-            options[:id] = name 
-        end
-        
+def option_parse
+       options = {}
+       banner = "Package-server administer service command-line tool." + "\n" \
+               + "\n" + "Usage: pkg-svr <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> -s <snapshot_name> [--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
+
+               opts.on( '-n', '--name <server name>', 'package server name' ) do|name|
+                       options[:id] = name
+               end
+
                opts.on( '-d', '--dist <distribution>', 'package server distribution' ) do|dist|
-            options[:dist] = dist 
-        end
-               
-               opts.on( '-u', '--url <server_address>', 'remote server address' ) do|url|
-            options[:url] = url 
-        end
-               
+                       options[:dist] = dist
+               end
+
+               opts.on( '-u', '--url <server url>', 'remote server url: http://127.0.0.1/dibs/unstable' ) do|url|
+                       options[:url] = url
+               end
+
                opts.on( '-o', '--os <operating system>', 'target operating system' ) do|os|
-            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(",")
-            list.each do |l|
-                               # TODO: is not working
-                #reg = Regexp.new(l)
-                #Dir.entries(Utils::WORKING_DIR).select{|x| x =~ reg}.each do |ls|
-                #    options[:bpkgs].push ls
-                               #end 
-                               if l.start_with? "~" then l = Utils::HOME + l.delete("~") end
-                               options[:bpkgs].push l 
-            end 
-        end
-               
-               opts.on( '-s', '--spackage <source_pakcage_file_path_list>', 'source package file path ' ) do|spkgs|
-            options[:spkgs] = []
-            list = spkgs.tr(" \t","").split(",")
-            list.each do |l|
+                       options[:os] = os
+               end
+
+               opts.on( '-P', '--pkgs <package file 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|
                                if l.start_with? "~" then l = Utils::HOME + l.delete("~") end
-                               options[:spkgs].push l 
-            end 
-        end
-               
-               opts.on( '-g', '--generate', 'snapshot is generate' ) do
-            options[:gensnap] = true
-               end
-
-               opts.on( '-n', '--sname <snapshot>', 'snapshot name' ) do|snap|
-            options[:snap] = snap 
-        end
-               
-               opts.on( '-b', '--bsnapshot <base_snapshot_name>', 'base snapshot name' ) do|bsnap|
-            options[:bsnap] = bsnap 
-        end
-               
-               opts.on( '-l', '--location <location>', 'server location' ) do|loc|
-            options[:loc] = loc 
-        end
-               
-               opts.on( '-f', '--force', 'force update pkg file' ) do
-            options[:force] = true
-        end
-               
-               opts.on( '-t', '--test', 'upload for test' ) do
-            options[:test] = true
-        end
-               
-               opts.on( '-c', '--clone', 'clone mode' ) do
-            options[:clone] = true
-        end
-               
-               opts.on( '-h', '--help', 'display this information' ) do
-            puts opts
+                               options[:pkgs].push l
+                       end
+               end
+
+               opts.on( '-s', '--snapshot <snapshot>', 'a snapshot name or snapshot list' ) do|snaplist|
+                       if not Utils.multi_argument_test( snaplist, "," ) then
+                               raise ArgumentError, "Snapshot variable parsing error : #{snaplist}"
+                       end
+                       options[:snaps] = snaplist.split(",")
+               end
+
+               opts.on( '-b', '--base <base snapshot>', 'base snapshot name' ) do|bsnap|
+                       options[:bsnap] = bsnap
+               end
+
+               opts.on( '-l', '--loc <location>', 'server location' ) do|loc|
+                       options[:loc] = loc
+               end
+
+               opts.on( '-p', '--port <port>', 'port number' ) do|port|
+                       options[:port] = port
+               end
+
+               opts.on( '-w', '--passwd <password>', 'password for package server' ) do|passwd|
+                       options[:passwd] = passwd
+               end
+
+               opts.on( '--clone', 'clone mode' ) do
+                       options[:clone] = true
+               end
+
+               opts.on( '--force', 'force update pkg file' ) do
+                       options[:force] = true
+               end
+
+               opts.on( '--test', 'upload for test' ) do
+                       options[:test] = true
+               end
+
+               opts.on( '--gen', 'generate snapshot' ) do
+                       options[:gensnap] = true
+               end
+
+               opts.on( '-h', '--help', 'display help' ) do
+                       puts opts
                        exit
-        end
-               
-    end
-    
-       cmd = ARGV[0] 
-
-    if cmd.eql? "create" or cmd.eql? "register" or cmd.eql? "sync" \
-                       or cmd.eql? "gen-snapshot" or cmd.eql? "add-dist" \
-                       or cmd.eql? "spkg-path" or cmd.eql? "remove" \
-                       or cmd.eql? "list" or cmd.eql? "remove-pkg" or cmd =~ /(help)|(-h)|(--help)/  then
-        if cmd.eql? "help" then ARGV[0] = "-h" end
-        options[:cmd] = ARGV[0]
-    else
-        raise ArgumentError, banner
-    end
-
-    optparse.parse!
-   
-       # default value setting 
+               end
+
+               opts.on( '-v', '--version', 'display version' ) do
+                       puts "DIBS(Distributed Intelligent Build System) version " + Utils.get_version()
+                       exit
+               end
+       end
+
+       cmd = ARGV[0]
+
+       if cmd.eql? "create" or cmd.eql? "sync" \
+               or cmd.eql? "register" \
+               or cmd.eql? "gen-snapshot" \
+               or cmd.eql? "add-dist" or cmd.eql? "add-os" \
+               or cmd.eql? "remove" or cmd.eql? "remove-dist" \
+               or cmd.eql? "remove-pkg" or cmd.eql? "remove-snapshot" \
+               or cmd.eql? "start" or cmd.eql? "stop" or cmd.eql? "clean" \
+               or cmd.eql? "list" \
+               or cmd =~ /(-v)|(--version)/ \
+               or cmd =~ /(help)|(-h)|(--help)/ then
+               if cmd.eql? "help" then ARGV[0] = "-h" end
+               options[:cmd] = ARGV[0]
+       else
+               raise ArgumentError, "Usage: pkg-svr <SUBCOMMAND> [OPTS] or pkg-svr -h"
+       end
+
+       # default value setting
        set_default options
 
-       # option error check 
+       optparse.parse!
+
+       # option error check
        option_error_check options
 
-    return options
-end 
+       return options
+end
 
diff --git a/test/bin/bin_0.0.0_linux.zip b/test/bin/bin_0.0.0_linux.zip
new file mode 100644 (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
diff --git a/test/build-server.basic1/build-cli-01.testcase b/test/build-server.basic1/build-cli-01.testcase
new file mode 100644 (file)
index 0000000..90e5080
--- /dev/null
@@ -0,0 +1,43 @@
+#PRE-EXEC
+#EXEC
+../../build-cli -h
+#POST-EXEC
+#EXPECT
+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] [-D <distribution name>] [-U user-email] [-V]
+build-cli resolve -N <project name> -d <server address> [-o <os>] [-w <password>] [--async] [-D <distribution name>] [-U user-email] [-V]
+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 <package file> -d <server address>  [-t <ftp server url>] [-w <password>] [-D <distribution name>] [-U user-email]
+
+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
+-D, --dist <distribution name>   distribution name
+-t, --ftp <ftp server url>       ftp server url: ftp://dibsftp:dibsftp@127.0.0.1
+-U, --user <user email>          user email infomation
+-V, --verbose                    verbose mode
+-h, --help                       display help
+-v, --version                    display version
diff --git a/test/build-server.basic1/build-cli-02.testcase b/test/build-server.basic1/build-cli-02.testcase
new file mode 100644 (file)
index 0000000..4d821bd
--- /dev/null
@@ -0,0 +1,29 @@
+#PRE-EXEC
+#EXEC
+../../build-cli query -d 127.0.0.1:2223
+#POST-EXEC
+#EXPECT
+* SYSTEM INFO *
+HOST-OS: ubuntu-32
+MAX_WORKING_JOBS: 2
+
+* FTP *
+FTP_ADDR:
+FTP_USERNAME:
+
+* SUPPORTED OS LIST *
+ubuntu-32
+windows-32
+
+* FRIEND SERVER LIST (WAIT|WORK/MAX) jobs [transfer count] *
+
+
+* PROJECT(S) *
+testa                     NORMAL
+testa1                    NORMAL
+testb                     NORMAL
+testc                     NORMAL
+testd                     NORMAL
+teste                     REMOTE
+
+* JOB(S) *
diff --git a/test/build-server.basic1/build-cli-03.testcase b/test/build-server.basic1/build-cli-03.testcase
new file mode 100644 (file)
index 0000000..b084d40
--- /dev/null
@@ -0,0 +1,30 @@
+#PRE-EXEC
+#EXEC
+../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32
+#POST-EXEC
+#EXPECT
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Checking build dependency ...
+Info: Checking install dependency ...
+Info: Started to build this job...
+Info: JobBuilder
+Info: Downloding client is initializing...
+Info: Installing dependent packages...
+Info: Downloading dependent source packages...
+Info: Make clean...
+Info: Make build...
+Info: Make install...
+Info: Generatiing pkginfo.manifest...
+Info: Zipping...
+Info: Creating package file ... a_0.0.1_ubuntu-32.zip
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "testa"
diff --git a/test/build-server.basic1/build-cli-03_1.testcase b/test/build-server.basic1/build-cli-03_1.testcase
new file mode 100644 (file)
index 0000000..5324ae3
--- /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-server.basic1/build-cli-04.testcase b/test/build-server.basic1/build-cli-04.testcase
new file mode 100644 (file)
index 0000000..977d486
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../../build-cli build -N non_exist_project -d 127.0.0.1:2223 -o ubuntu-32
+#POST-EXEC
+#EXPECT
+Error: Project not found!: non_exist_project on BASE
diff --git a/test/build-server.basic1/build-cli-05.testcase b/test/build-server.basic1/build-cli-05.testcase
new file mode 100644 (file)
index 0000000..0072e13
--- /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-server.basic1/build-cli-06.testcase b/test/build-server.basic1/build-cli-06.testcase
new file mode 100644 (file)
index 0000000..1682338
--- /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-server.basic1/build-cli-07.testcase b/test/build-server.basic1/build-cli-07.testcase
new file mode 100644 (file)
index 0000000..10e64d4
--- /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-server.basic1/build-cli-08.testcase b/test/build-server.basic1/build-cli-08.testcase
new file mode 100644 (file)
index 0000000..6d08be1
--- /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-server.basic1/build-cli-09.testcase b/test/build-server.basic1/build-cli-09.testcase
new file mode 100644 (file)
index 0000000..b20cb5b
--- /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-server.basic1/build-cli-10.testcase b/test/build-server.basic1/build-cli-10.testcase
new file mode 100644 (file)
index 0000000..c585766
--- /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-server.basic1/build-cli-11.testcase b/test/build-server.basic1/build-cli-11.testcase
new file mode 100644 (file)
index 0000000..beb3e82
--- /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-server.basic1/build-cli-12.testcase b/test/build-server.basic1/build-cli-12.testcase
new file mode 100644 (file)
index 0000000..a0b9e6f
--- /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 used!: wrong_os_name
+Supported OS list.
+* ubuntu-32
+* windows-32
diff --git a/test/build-server.basic1/build-cli-12_1.testcase b/test/build-server.basic1/build-cli-12_1.testcase
new file mode 100644 (file)
index 0000000..cccfe9f
--- /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 used!: wrong_os_name
+Supported OS list.
+* ubuntu-32
+* windows-32
diff --git a/test/build-server.basic1/build-cli-13.testcase b/test/build-server.basic1/build-cli-13.testcase
new file mode 100644 (file)
index 0000000..59fd045
--- /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-server.basic1/build-cli-14.testcase b/test/build-server.basic1/build-cli-14.testcase
new file mode 100644 (file)
index 0000000..df9fff2
--- /dev/null
@@ -0,0 +1,8 @@
+#PRE-EXEC
+echo "Assume that testc project has the password (1111)"
+echo "Assume that testa,testb which are depended by testc are built and uploaded"
+#EXEC
+../../build-cli build -N testc -d 127.0.0.1:2223 -o ubuntu-32
+#POST-EXEC
+#EXPECT
+Error: Project password required!: Use -w option to input your project password
diff --git a/test/build-server.basic1/build-cli-15.testcase b/test/build-server.basic1/build-cli-15.testcase
new file mode 100644 (file)
index 0000000..9b7cd98
--- /dev/null
@@ -0,0 +1,8 @@
+#PRE-EXEC
+echo "Assume that testc project has the password (1111)"
+echo "Assume that testa,testb which are depended by testc are built and uploaded"
+#EXEC
+../../build-cli build -N testc -d 127.0.0.1:2223 -w 2222 -o ubuntu-32
+#POST-EXEC
+#EXPECT
+Error: Project password not matched!
diff --git a/test/build-server.basic1/build-cli-16.testcase b/test/build-server.basic1/build-cli-16.testcase
new file mode 100644 (file)
index 0000000..1f798aa
--- /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-server.basic1/build-cli-17.testcase b/test/build-server.basic1/build-cli-17.testcase
new file mode 100644 (file)
index 0000000..9653e45
--- /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-server.basic1/build-cli-18.testcase b/test/build-server.basic1/build-cli-18.testcase
new file mode 100644 (file)
index 0000000..32218a2
--- /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-server.basic1/build-cli-19.testcase b/test/build-server.basic1/build-cli-19.testcase
new file mode 100644 (file)
index 0000000..076004e
--- /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-server.basic1/build-cli-20.testcase b/test/build-server.basic1/build-cli-20.testcase
new file mode 100644 (file)
index 0000000..e475cf8
--- /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-server.basic1/build-cli-21.testcase b/test/build-server.basic1/build-cli-21.testcase
new file mode 100644 (file)
index 0000000..5de4383
--- /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-server.basic1/build-cli-22.testcase b/test/build-server.basic1/build-cli-22.testcase
new file mode 100644 (file)
index 0000000..9ee83c9
--- /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-server.basic1/build-cli-23.testcase b/test/build-server.basic1/build-cli-23.testcase
new file mode 100644 (file)
index 0000000..44ff734
--- /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-server.basic1/build-cli-24.testcase b/test/build-server.basic1/build-cli-24.testcase
new file mode 100644 (file)
index 0000000..de1b348
--- /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-server.basic1/build-cli-25.testcase b/test/build-server.basic1/build-cli-25.testcase
new file mode 100644 (file)
index 0000000..adaeb98
--- /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-server.basic1/build-cli-26.testcase b/test/build-server.basic1/build-cli-26.testcase
new file mode 100644 (file)
index 0000000..eb0965c
--- /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-server.basic1/build-cli-27.testcase b/test/build-server.basic1/build-cli-27.testcase
new file mode 100644 (file)
index 0000000..66eb1cf
--- /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: Unsupported OS name used!: There is no OS name matched.
diff --git a/test/build-server.basic1/build-cli-28.testcase b/test/build-server.basic1/build-cli-28.testcase
new file mode 100644 (file)
index 0000000..27dfb11
--- /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-server.basic1/build-cli-29.testcase b/test/build-server.basic1/build-cli-29.testcase
new file mode 100644 (file)
index 0000000..47d1580
--- /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-server.basic1/build-cli-30.testcase b/test/build-server.basic1/build-cli-30.testcase
new file mode 100644 (file)
index 0000000..2fe774e
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+echo "user check"
+#EXEC
+../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 -U xxuser@user
+#POST-EXEC
+#EXPECT
+Error: User account not found!: xxuser@user
diff --git a/test/build-server.basic1/buildsvr.init b/test/build-server.basic1/buildsvr.init
new file mode 100755 (executable)
index 0000000..72cf1fe
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+
+if [ ! "$DB_PASSWD" ] ; then
+       read -p "Insert DB password: " input
+       export DB_PASSWD=$input
+else
+       echo $DB_PASSWD
+fi
+
+rm -rf buildsvr01
+rm -rf git01
+rm -rf bin
+rm -rf ~/.build_tools/build_server/testserver3
+
+../../build-svr remove -n testserver3
+mkdir buildsvr01
+cd buildsvr01
+${RUBY} ../../../build-svr create -n testserver3
+echo "DROP DATABASE testserver3;" > a
+mysql -u root -p --password=$DB_PASSWD -h localhost < a
+${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD
+rm -f a
+cd ..
+${RUBY} ../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333
+${RUBY} ../../build-svr add-svr -n testserver3 -d 127.0.0.1:2224
+${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32
+${RUBY} ../../build-svr add-os -n testserver3 -o windows-32
+${RUBY} ../../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testc -g `pwd`/git01/c -b master -w 1111
+${RUBY} ../../build-svr add-prj -n testserver3 -N testd -g `pwd`/git01/d -b master -o ubuntu-32
+${RUBY} ../../build-svr add-prj -n testserver3 -N teste -P bin
+${RUBY} ../../build-svr add-prj -n testserver3 -N testa1 -g `pwd`/git01/a1 -b master
+
+mkdir -p git01
+cp ../git01/*.tar.gz git01/
+cd git01
+rm -rf a
+rm -rf a1
+rm -rf b
+rm -rf c
+rm -rf d
+tar xvf a_v1.tar.gz
+tar xvf b_v1.tar.gz
+tar xvf c_v1.tar.gz
+tar xvf d_v0.tar.gz
+tar xvf a1_v1.tar.gz
+cd ..
+
+mkdir -p bin
+cp ../bin/* bin/
+
+${RUBY} ../../pkg-svr register -n pkgsvr01 -d unstable -P bin/bin_0.0.0_ubuntu-32.zip
+
+${RUBY}  ../../build-svr start -n testserver3 -p 2223 --CHILD
diff --git a/test/build-server.basic1/pkgsvr.init b/test/build-server.basic1/pkgsvr.init
new file mode 100755 (executable)
index 0000000..6973d9e
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+       RUBY="ruby -d"
+fi
+rm -rf ~/.build_tools/pkg_server/pkgsvr01
+rm -rf `pwd`/pkgsvr01
+${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32
+${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333
diff --git a/test/build-server.basic1/testsuite b/test/build-server.basic1/testsuite
new file mode 100644 (file)
index 0000000..b5b5903
--- /dev/null
@@ -0,0 +1,31 @@
+build-cli-01.testcase
+build-cli-02.testcase
+build-cli-03.testcase
+build-cli-04.testcase
+build-cli-05.testcase
+build-cli-06.testcase
+build-cli-07.testcase
+build-cli-08.testcase
+build-cli-09.testcase
+build-cli-10.testcase
+build-cli-11.testcase
+build-cli-12.testcase
+build-cli-12_1.testcase
+build-cli-13.testcase
+build-cli-14.testcase
+build-cli-15.testcase
+build-cli-16.testcase
+build-cli-17.testcase
+build-cli-18.testcase
+build-cli-19.testcase
+build-cli-20.testcase
+build-cli-21.testcase
+build-cli-22.testcase
+build-cli-23.testcase
+build-cli-24.testcase
+build-cli-25.testcase
+build-cli-26.testcase
+build-cli-27.testcase
+build-cli-28.testcase
+build-cli-29.testcase
+build-cli-30.testcase
diff --git a/test/build-server.basic2/build-svr-01.testcase b/test/build-server.basic2/build-svr-01.testcase
new file mode 100644 (file)
index 0000000..f9617b1
--- /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://ftpuser:ftpuser@172.21.111.124
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Created new build server: "testserver3"
diff --git a/test/build-server.basic2/build-svr-02.testcase b/test/build-server.basic2/build-svr-02.testcase
new file mode 100644 (file)
index 0000000..271b3c0
--- /dev/null
@@ -0,0 +1,79 @@
+#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|-v)
+
+Subcommands:
+create        Create the build-server.
+remove        Remove the build-server.
+migrate       build-server DB migrate.
+start         Start the build-server.
+stop          Stop the build-server.
+upgrade       Upgrade the build-server include friends.
+add-svr       Add remote build/package server for support multi-OS or distribute build job.
+remove-svr    Remove remote build/package server for support multi-OS or distribute build job.
+add-os        Add supported OS.
+remove-os     Remove supported OS.
+add-dist      Add distribution.
+remove-dist   Remove distribution.
+lock-dist     Lock distribution.
+unlock-dist   Unlock distribution.
+add-sync      Add package repository URL to synchronize with.
+remove-sync   Remove package repository URL.
+add-prj       Add project to build.
+remove-prj    Remove project.
+register      Register the package to the build-server.
+fullbuild     Build all your projects and upload them to package server.
+query         Show build server configuration.
+set-attr      Set build server atribute.
+get-attr      Get build server atribute.
+
+Subcommand usage:
+build-svr create -n <server name> [-t <ftp server url>]
+build-svr remove -n <server name>
+build-svr migrate -n <server name> [--dsn <db dsn> [--dbuser <db_user> --dbpassword <db_password>] ]
+build-svr start -n <server name> -p <port>
+build-svr stop -n <server name>
+build-svr upgrade -n <server name>
+build-svr add-svr -n <server name> -d <friend server address>
+build-svr remove-svr -n <server name> -d <friend server address>
+build-svr add-os -n <server name> -o <os>
+build-svr remove-os -n <server name> -o <os>
+build-svr add-dist -n <server name> -D <distribution name> -u <package server url> -d <package server address>
+build-svr remove-dist -n <server name> -D <distribution name>
+build-svr lock-dist -n <server name> -D <distribution name>
+build-svr unlock-dist -n <server name> -D <distribution name>
+build-svr add-sync -n <server name> -u <remote pkg server url> [--dist <distribution>]
+build-svr remove-sync -n <server name> -u <remote pkg server url> [--dist <distribution>]
+build-svr add-prj -n <server name> -N <project name> (-g <git repository> -b <git branch>|-P <package name>) [-w <password>] [-o <os list>] [--dist <distribution>]
+build-svr remove-prj -n <server name> -N <project name> [--dist <distribution>]
+build-svr fullbuild -n <server name> [--dist <distribution>]
+build-svr register -n <server name> -P <package file> [--dist <distribution>]
+build-svr query -n <server name>
+build-svr set-attr -n <server name> -A <attribute> -V <value>
+build-svr get-attr -n <server name> -A <attribute>
+
+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) ubuntu-32,windows-32
+-N, --pname <project name>       project name
+-g, --git <git repository>       git repository
+-b, --branch <git branch>        git branch
+-D, --dist <distribution name>   distribution name
+-w, --passwd <password>          password for managing project
+-t, --ftp <ftp server url>       ftp server url: ftp://dibsftp:dibsftp@127.0.0.1:1024
+-A, --attr <attribute name>      attribute
+--dsn <dsn>                  Data Source Name ex) mysql:host=localhost;database=test
+--dbuser <user>              DB user id
+--dbpassword <password>      DB password
+-V, --value <value>              value
+-h, --help                       display this information
+-v, --version                    display version
diff --git a/test/build-server.basic2/build-svr-03.testcase b/test/build-server.basic2/build-svr-03.testcase
new file mode 100644 (file)
index 0000000..236a9ef
--- /dev/null
@@ -0,0 +1,24 @@
+#PRE-EXEC
+rm -rf buildsvr01
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 
+#EXEC
+../../build-svr add-svr -n testserver3 -d 127.0.0.1:2223
+../../build-svr query -n testserver3
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Friend server is added successfully!
+* REMOTE SERVER(S) *
+* 127.0.0.1:2223
+
+* SUPPORTED OS *
+
+* DISTRIBUTION(S) *
+* BASE
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
diff --git a/test/build-server.basic2/build-svr-04.testcase b/test/build-server.basic2/build-svr-04.testcase
new file mode 100644 (file)
index 0000000..985f511
--- /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
+echo "TEST_TIME=3" >> ~/.build_tools/build_server/testserver3/server.cfg
+../../build-svr start -n testserver3 -p 2223
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
diff --git a/test/build-server.basic2/build-svr-05.testcase b/test/build-server.basic2/build-svr-05.testcase
new file mode 100644 (file)
index 0000000..23d530f
--- /dev/null
@@ -0,0 +1,15 @@
+#PRE-EXEC
+mkdir buildsvr01
+rm -rf ~/.build_tools/build_server/testserver3
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+../../build-svr start -n testserver3 -p 2223 &
+#EXEC
+sleep 1
+../../build-svr stop -n testserver3
+sleep 1
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Server will be down!
diff --git a/test/build-server.basic2/build-svr-06.testcase b/test/build-server.basic2/build-svr-06.testcase
new file mode 100644 (file)
index 0000000..b3f62fe
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132
+#EXEC
+../../build-svr stop -n testserver3
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+generating
+Server is not running!
diff --git a/test/build-server.basic2/build-svr-07.testcase b/test/build-server.basic2/build-svr-07.testcase
new file mode 100644 (file)
index 0000000..b5518f5
--- /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-server.basic2/build-svr-08.testcase b/test/build-server.basic2/build-svr-08.testcase
new file mode 100644 (file)
index 0000000..3ab2171
--- /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-server.basic2/build-svr-09.testcase b/test/build-server.basic2/build-svr-09.testcase
new file mode 100644 (file)
index 0000000..2a301eb
--- /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-server.basic2/build-svr-10.testcase b/test/build-server.basic2/build-svr-10.testcase
new file mode 100644 (file)
index 0000000..1d3f863
--- /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-server.basic2/build-svr-11.testcase b/test/build-server.basic2/build-svr-11.testcase
new file mode 100644 (file)
index 0000000..0b2f399
--- /dev/null
@@ -0,0 +1,13 @@
+#PRE-EXEC
+rm -rf buildsvr01
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+../../build-svr add-os -n testserver3 -o ubuntu-32
+#EXEC
+../../build-svr add-prj -n testserver3 -N testa -g test_git -b test_branch
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Adding project succeeded!
diff --git a/test/build-server.basic2/build-svr-12.testcase b/test/build-server.basic2/build-svr-12.testcase
new file mode 100644 (file)
index 0000000..1dcbb18
--- /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-server.basic2/build-svr-13.testcase b/test/build-server.basic2/build-svr-13.testcase
new file mode 100644 (file)
index 0000000..f87355b
--- /dev/null
@@ -0,0 +1,10 @@
+#PRE-EXEC
+rm -rf buildsvr01
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+#EXEC
+../../build-svr add-prj -n testserver3 -N testa -g test_git -b test_branch -w 1111
+#POST-EXEC
+#EXPECT
+Adding project succeeded!
diff --git a/test/build-server.basic2/build-svr-14.testcase b/test/build-server.basic2/build-svr-14.testcase
new file mode 100644 (file)
index 0000000..ce59935
--- /dev/null
@@ -0,0 +1,14 @@
+#PRE-EXEC
+rm -rf buildsvr01
+rm -rf ~/.build_tools/build_server/testserver3
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+../../build-svr add-os -n testserver3 -o ubuntu-32
+#EXEC
+../../build-svr add-prj -n testserver3 -N testx -g test_git -b test_branch -o ubuntu-32
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Adding project succeeded!
diff --git a/test/build-server.basic2/build-svr-15.testcase b/test/build-server.basic2/build-svr-15.testcase
new file mode 100644 (file)
index 0000000..734b5a7
--- /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_ubuntu-32.zip
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for REGISTER Job
+Info: New Job
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
diff --git a/test/build-server.basic2/build-svr-16.testcase b/test/build-server.basic2/build-svr-16.testcase
new file mode 100644 (file)
index 0000000..b5fe4fc
--- /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_ubuntu-32.zip
+#EXEC
+../../build-svr register -n testserver3 -P bin/bin_0.0.0_ubuntu-32.zip
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Info: Initializing job...
+Info: Checking package version ...
+Error: Version must be increased :
+Error: Job is stopped by ERROR
diff --git a/test/build-server.basic2/build-svr-17.testcase b/test/build-server.basic2/build-svr-17.testcase
new file mode 100644 (file)
index 0000000..244ce63
--- /dev/null
@@ -0,0 +1,24 @@
+#PRE-EXEC
+rm -rf buildsvr01
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://dibsftp:coreps2@172.21.111.132
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+#EXEC
+../../build-svr add-os -n testserver3 -o ubuntu-32
+../../build-svr query -n testserver3
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Target OS is added successfully!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* BASE
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
diff --git a/test/build-server.basic2/build-svr-18.testcase b/test/build-server.basic2/build-svr-18.testcase
new file mode 100644 (file)
index 0000000..d2517ee
--- /dev/null
@@ -0,0 +1,14 @@
+#PRE-EXEC
+rm -rf buildsvr01
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333 -t ftp://dibsftp:coreps2@172.21.111.132
+#EXEC
+../../build-svr add-os -n testserver3 -o ubuntu-32
+../../build-svr add-os -n testserver3 -o ubuntu-32
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+generating
+Target OS is added successfully!
+Target OS already exists in list!
diff --git a/test/build-server.basic2/build-svr-19.testcase b/test/build-server.basic2/build-svr-19.testcase
new file mode 100644 (file)
index 0000000..5a7ce72
--- /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 ubuntu-32
+../../build-svr add-os -n testserver3 -o windows-32
+#EXEC
+../../build-svr add-prj -n testserver3 -N new_project -g new_git -b new_branch -o wrong_os_name
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+Unsupported OS name "wrong_os_name" is used!
+Check the following supported OS list:
+ * ubuntu-32
+ * windows-32
diff --git a/test/build-server.basic2/build-svr-20.testcase b/test/build-server.basic2/build-svr-20.testcase
new file mode 100644 (file)
index 0000000..1396b9c
--- /dev/null
@@ -0,0 +1,22 @@
+#PRE-EXEC
+rm -rf buildsvr01
+mkdir buildsvr01
+cd buildsvr01; ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@172.21.111.124
+cd buildsvr01; ../../../build-svr add-dist -n testserver3 -D BASE -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+../../build-svr add-os -n testserver3 -o ubuntu-32
+mkdir -p bin
+cp ../bin/bin_0.0.0_ubuntu-32.zip bin/bin_0.0.0_wrongosname.zip
+../../build-svr start -n testserver3 -p 2223 &
+#EXEC
+sleep 1
+../../build-svr register -n testserver3 -P bin/bin_0.0.0_wrongosname.zip
+#POST-EXEC
+../../build-svr stop -n testserver3
+sleep 1
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+rm -rf bin/bin/bin_0.0.0_wrongosname.zip
+#EXPECT
+Info: Initializing job...
+Error: Unsupported OS "wrongosname" is used!
+Error: Job is stopped by ERROR
diff --git a/test/build-server.basic2/build-svr-21.testcase b/test/build-server.basic2/build-svr-21.testcase
new file mode 100644 (file)
index 0000000..b703113
--- /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://ftpuser:ftpuser@172.21.111.124
+cd buildsvr01; ../../../build-svr migrate -n testserver3
+#EXEC
+../../build-svr set-attr -n testserver3 -A MAX_WORKING_JOBS -V 3
+../../build-svr get-attr -n testserver3 -A MAX_WORKING_JOBS
+../../build-svr set-attr -n testserver3 -A XXX
+../../build-svr set-attr -n testserver3 -A XXX -V 1
+../../build-svr get-attr -n testserver3 -A XXX
+
+#POST-EXEC
+../../build-svr remove -n testserver3
+rm -rf buildsvr01
+#EXPECT
+3
+Usage: build-svr set-attr -n <server name> -A <attribute> -V <value>
+Wrong attribute name!
+Wrong attribute name!
diff --git a/test/build-server.basic2/testsuite b/test/build-server.basic2/testsuite
new file mode 100644 (file)
index 0000000..05f65d2
--- /dev/null
@@ -0,0 +1,19 @@
+build-svr-01.testcase
+build-svr-02.testcase
+build-svr-03.testcase
+build-svr-04.testcase
+build-svr-05.testcase
+build-svr-06.testcase
+build-svr-07.testcase
+build-svr-08.testcase
+build-svr-09.testcase
+build-svr-10.testcase
+build-svr-11.testcase
+build-svr-12.testcase
+build-svr-13.testcase
+build-svr-14.testcase
+build-svr-17.testcase
+build-svr-18.testcase
+build-svr-19.testcase
+build-svr-20.testcase
+build-svr-21.testcase
diff --git a/test/build-server.multi-svr1/01.testcase b/test/build-server.multi-svr1/01.testcase
new file mode 100644 (file)
index 0000000..21843e1
--- /dev/null
@@ -0,0 +1,45 @@
+#PRE-EXEC
+#EXEC
+../../build-cli build -N testa -d 127.0.0.1:2223 -o ubuntu-32 -D unstable
+#POST-EXEC
+#EXPECT
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Started to build this job...
+Info: JobBuilder#
+Info: Start to build on remote server...
+Info: Sending build request to remote server...
+Info: Added new job
+Info: Initializing job...
+Info: Copying external dependent pkgs...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Started to build this job...
+Info: JobBuilder
+Info: Downloding client is initializing...
+Info: Installing dependent packages...
+Info: Downloading dependent source packages...
+Info: Make clean...
+Info: Make build...
+Info: Make install...
+Info: Generatiing pkginfo.manifest...
+Info: Zipping...
+Info: Creating package file ... a_0.0.1_ubuntu-32.zip
+Info: Copying log to
+Info: Copying result files to
+Info:  *
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "UNNAMED
+Info: Receiving log file from remote server...
+Info: Receiving file from remote server : a_0.0.1_ubuntu-32.zip
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "testa"
diff --git a/test/build-server.multi-svr1/02.testcase b/test/build-server.multi-svr1/02.testcase
new file mode 100644 (file)
index 0000000..cbe7440
--- /dev/null
@@ -0,0 +1,46 @@
+#PRE-EXEC
+#EXEC
+../../build-cli build -N testb -d 127.0.0.1:2223 -o ubuntu-32 -D unstable
+#POST-EXEC
+#EXPECT
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Started to build this job...
+Info: JobBuilder
+Info: Start to build on remote server...
+Info: Sending build request to remote server...
+Info: Added new job
+Info: Initializing job...
+Info: Copying external dependent pkgs...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Started to build this job...
+Info: JobBuilder
+Info: Downloding client is initializing...
+Info: Installing dependent packages...
+Info:  * a
+Info: Downloading dependent source packages...
+Info: Make clean...
+Info: Make build...
+Info: Make install...
+Info: Generatiing pkginfo.manifest...
+Info: Zipping...
+Info: Creating package file ... b_0.0.1_ubuntu-32.zip
+Info: Copying log to
+Info: Copying result files to
+Info:  *
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "UNNAMED
+Info: Receiving log file from remote server...
+Info: Receiving file from remote server : b_0.0.1_ubuntu-32.zip
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "testb"
diff --git a/test/build-server.multi-svr1/buildsvr1.init b/test/build-server.multi-svr1/buildsvr1.init
new file mode 100755 (executable)
index 0000000..9b0af28
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+
+if [ ! "$DB_PASSWD" ] ; then
+       echo -n "insert Mysql password : "
+       read input
+       export DB_PASSWD=$input
+else
+       echo $DB_PASSWD
+fi
+
+rm -rf buildsvr01
+rm -rf git01
+rm -rf bin
+rm -rf ~/.build_tools/build_server/testserver3
+
+../../build-svr remove -n testserver3
+mkdir buildsvr01
+cd buildsvr01
+${RUBY} ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1
+echo "DROP DATABASE testserver3;" > a
+mysql -u root -p --password=$DB_PASSWD -h localhost < a
+${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD
+rm -f a
+cd ..
+
+${RUBY} ../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333
+${RUBY} ../../build-svr add-svr -n testserver3 -d 127.0.0.1:2224
+${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32
+${RUBY} ../../build-svr add-os -n testserver3 -o windows-32
+${RUBY} ../../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master
+${RUBY} ../../build-svr set-attr -n testserver3 -A MAX_WORKING_JOBS -V 0
+
+mkdir -p git01
+cp ../git01/*.tar.gz git01/
+cd git01
+rm -rf a
+rm -rf b
+tar xvf a_v1.tar.gz
+tar xvf b_v1.tar.gz
+cd ..
+
+${RUBY} ../../build-svr start -n testserver3 -p 2223 --CHILD
diff --git a/test/build-server.multi-svr1/buildsvr2.init b/test/build-server.multi-svr1/buildsvr2.init
new file mode 100755 (executable)
index 0000000..56b8da5
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+
+if [ ! "$DB_PASSWD" ] ; then
+       read -p "Insert DB password: " input
+       export DB_PASSWD=$input
+else
+       echo $DB_PASSWD
+fi
+
+rm -rf buildsvr02
+
+../../build-svr remove -n testserver4
+mkdir buildsvr02
+cd buildsvr02
+${RUBY} ../../../build-svr create -n testserver4
+echo "DROP DATABASE testserver4;" > a
+mysql -u root -p --password=$DB_PASSWD -h localhost < a
+${RUBY} ../../../build-svr migrate -n testserver4 --dsn Mysql:testserver4:localhost --dbuser root --dbpassword $DB_PASSWD
+rm -f a
+cd ..
+${RUBY} ../../build-svr add-dist -n testserver4 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333
+
+${RUBY} ../../build-svr start -n testserver4 -p 2224 --CHILD
diff --git a/test/build-server.multi-svr1/pkgsvr.init b/test/build-server.multi-svr1/pkgsvr.init
new file mode 100755 (executable)
index 0000000..0cc21e3
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+rm -rf ~/.build_tools/pkg_server/pkgsvr01
+rm -rf `pwd`/pkgsvr01
+${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32
+${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333
diff --git a/test/build-server.multi-svr1/testsuite b/test/build-server.multi-svr1/testsuite
new file mode 100644 (file)
index 0000000..960eff3
--- /dev/null
@@ -0,0 +1,2 @@
+01.testcase
+02.testcase
diff --git a/test/build-server.multi-svr2/01.testcase b/test/build-server.multi-svr2/01.testcase
new file mode 100644 (file)
index 0000000..f71a53f
--- /dev/null
@@ -0,0 +1,23 @@
+#PRE-EXEC
+#EXEC
+../../pkg-svr register -n pkgsvr02 -d unstable -P bin/bin_0.0.1_ubuntu-32.zip
+sleep 50
+../../pkg-cli list-rpkg -P bin -u `pwd`/pkgsvr01/unstable
+#POST-EXEC
+#EXPECT
+Archive:  bin/bin_0.0.1_ubuntu-32.zip
+inflating:
+snapshot is generated :
+package registed successfully
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+bin  (0.0.1)
diff --git a/test/build-server.multi-svr2/buildsvr.init b/test/build-server.multi-svr2/buildsvr.init
new file mode 100755 (executable)
index 0000000..b0859c9
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+
+if [ ! "$DB_PASSWD" ] ; then
+       read -p "Insert DB password: " input
+       export DB_PASSWD=$input
+else
+       echo $DB_PASSWD
+fi
+
+rm -rf buildsvr01
+rm -rf git01
+rm -rf bin
+rm -rf ~/.build_tools/build_server/testserver3
+
+../../build-svr remove -n testserver3
+mkdir buildsvr01
+cd buildsvr01
+${RUBY} ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1
+echo "DROP DATABASE testserver3;" > a
+mysql -u root -p --password=$DB_PASSWD -h localhost < a
+${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD
+rm -f a
+cd ..
+
+${RUBY} ../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333
+${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32
+${RUBY} ../../build-svr add-os -n testserver3 -o windows-32
+${RUBY} ../../build-svr add-prj -n testserver3 -N teste -P bin -D unstable -o ubuntu-32
+${RUBY} ../../build-svr add-sync -n testserver3 -u `pwd`/pkgsvr02/unstable -D unstable
+
+mkdir -p bin
+cp ../bin/*.zip ./bin/
+
+${RUBY} ../../build-svr start -n testserver3 -p 2223 --CHILD
diff --git a/test/build-server.multi-svr2/pkgsvr1.init b/test/build-server.multi-svr2/pkgsvr1.init
new file mode 100755 (executable)
index 0000000..0cc21e3
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+rm -rf ~/.build_tools/pkg_server/pkgsvr01
+rm -rf `pwd`/pkgsvr01
+${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32
+${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333
diff --git a/test/build-server.multi-svr2/pkgsvr2.init b/test/build-server.multi-svr2/pkgsvr2.init
new file mode 100755 (executable)
index 0000000..46ec0a7
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+rm -rf ~/.build_tools/pkg_server/pkgsvr02
+rm -rf `pwd`/pkgsvr02
+${RUBY} ../../pkg-svr create -n pkgsvr02 -d unstable
+${RUBY} ../../pkg-svr add-os -n pkgsvr02 -d unstable -o ubuntu-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr02 -d unstable -o windows-32
+${RUBY} ../../pkg-svr start -n pkgsvr02 -p 3334
diff --git a/test/build-server.multi-svr2/testsuite b/test/build-server.multi-svr2/testsuite
new file mode 100644 (file)
index 0000000..1bb2eb2
--- /dev/null
@@ -0,0 +1 @@
+01.testcase
diff --git a/test/build-server.multi_dist1/build-svr2-01.testcase b/test/build-server.multi_dist1/build-svr2-01.testcase
new file mode 100644 (file)
index 0000000..fb3d879
--- /dev/null
@@ -0,0 +1,23 @@
+#PRE-EXEC
+rm -rf buildsvr01
+rm -rf ~/.build_tools/build_server/testserver3
+mkdir buildsvr01
+cd buildsvr01;../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1
+../../build-svr add-os -n testserver3 -o ubuntu-32
+../../build-svr add-os -n testserver3 -o ubuntu-64
+#EXEC
+../../build-svr remove-os -n testserver3 -o ubuntu-64
+../../build-svr query -n testserver3
+#POST-EXEC
+#EXPECT
+Target OS is removed successfully!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
diff --git a/test/build-server.multi_dist1/build-svr2-02.testcase b/test/build-server.multi_dist1/build-svr2-02.testcase
new file mode 100644 (file)
index 0000000..9298235
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+echo "no os"
+#EXEC
+../../build-svr remove-os -n testserver3 -o ubuntu-644
+#POST-EXEC
+#EXPECT
+Target OS does not exist in list!
diff --git a/test/build-server.multi_dist1/build-svr2-03.testcase b/test/build-server.multi_dist1/build-svr2-03.testcase
new file mode 100644 (file)
index 0000000..06f96c2
--- /dev/null
@@ -0,0 +1,18 @@
+#PRE-EXEC
+#EXEC
+../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+../../build-svr query -n testserver3
+#POST-EXEC
+#EXPECT
+Distribution is added successfully!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
diff --git a/test/build-server.multi_dist1/build-svr2-04.testcase b/test/build-server.multi_dist1/build-svr2-04.testcase
new file mode 100644 (file)
index 0000000..c667dfc
--- /dev/null
@@ -0,0 +1,19 @@
+#PRE-EXEC
+../../build-svr add-dist -n testserver3 -D unstable2 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+#EXEC
+../../build-svr remove-dist -n testserver3 -D unstable2
+../../build-svr query -n testserver3
+#POST-EXEC
+#EXPECT
+Distribution is removed successfully!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
diff --git a/test/build-server.multi_dist1/build-svr2-05.testcase b/test/build-server.multi_dist1/build-svr2-05.testcase
new file mode 100644 (file)
index 0000000..b08491d
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../../build-svr remove-dist -n testserver3 -D unstable22
+#POST-EXEC
+#EXPECT
+Distribution does not exist in list!
diff --git a/test/build-server.multi_dist1/build-svr2-06.testcase b/test/build-server.multi_dist1/build-svr2-06.testcase
new file mode 100644 (file)
index 0000000..685d52a
--- /dev/null
@@ -0,0 +1,66 @@
+#PRE-EXEC
+#EXEC
+../../build-svr add-sync -n testserver3 -u http://xxx
+../../build-svr query -n testserver3
+../../build-svr add-sync -n testserver3 -D unstable -u http://yyy
+../../build-svr query -n testserver3
+../../build-svr remove-sync -n testserver3 -u http://yyy
+../../build-svr query -n testserver3
+../../build-svr remove-sync -n testserver3 -D unstable testserver3 -u http://xxx
+../../build-svr query -n testserver3
+../../build-svr remove-sync -n testserver3 -D unstable testserver3 -u http://xxxyyyy
+#POST-EXEC
+#EXPECT
+Remote package server is added!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+* [unstable] http://xxx
+
+* PROJECT(S) *
+Remote package server is added!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+* [unstable] http://xxx
+* [unstable] http://yyy
+
+* PROJECT(S) *
+Remote package server is removed!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+* [unstable] http://xxx
+
+* PROJECT(S) *
+Remote package server is removed!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
+The server does not exist in list!
diff --git a/test/build-server.multi_dist1/build-svr2-07.testcase b/test/build-server.multi_dist1/build-svr2-07.testcase
new file mode 100644 (file)
index 0000000..6afd8c9
--- /dev/null
@@ -0,0 +1,78 @@
+#PRE-EXEC
+../../build-svr add-dist -n testserver3 -D unstable2 -u `pwd`/../pkgsvr01/unstable -d 127.0.0.1:3333
+#EXEC
+../../build-svr add-prj -n testserver3 -N test1 -g test1_git -b test1_branch
+../../build-svr query -n testserver3
+../../build-svr add-prj -n testserver3 -D unstable -N test2 -g test1_git -b test1_branch
+../../build-svr add-prj -n testserver3 -D unstable2 -N test1 -g test1_git -b test1_branch
+../../build-svr query -n testserver3
+../../build-svr remove-prj -n testserver3 -N test1
+../../build-svr query -n testserver3
+../../build-svr remove-prj -n testserver3 -D unstable -N test2
+../../build-svr remove-prj -n testserver3 -D unstable2 -N test1
+../../build-svr query -n testserver3
+../../build-svr remove-prj -n testserver3 -D unstable -N testxxx
+#POST-EXEC
+../../build-svr remove-dist -n testserver3 -D unstable2
+#EXPECT
+Adding project succeeded!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+* unstable2
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
+* [unstable]  test1
+Adding project succeeded!
+Adding project succeeded!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+* unstable2
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
+* [unstable]  test1
+* [unstable]  test2
+* [unstable2]  test1
+Removing project succeeded!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+* unstable2
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
+* [unstable]  test2
+* [unstable2]  test1
+Removing project succeeded!
+Removing project succeeded!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+* unstable2
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
+Removing project failed!
diff --git a/test/build-server.multi_dist1/build-svr2-08.testcase b/test/build-server.multi_dist1/build-svr2-08.testcase
new file mode 100644 (file)
index 0000000..90ef0b4
--- /dev/null
@@ -0,0 +1,21 @@
+#PRE-EXEC
+#EXEC
+../../build-svr add-prj -n testserver3 -D unstable -N testbin -P bin
+../../build-svr query -n testserver3
+../../build-svr remove-prj -n testserver3 -N testbin -D unstable
+#POST-EXEC
+#EXPECT
+Adding project succeeded!
+* REMOTE SERVER(S) *
+
+* SUPPORTED OS *
+* ubuntu-32
+
+* DISTRIBUTION(S) *
+* unstable
+
+* SYNC PACKAGE SERVER(S) *
+
+* PROJECT(S) *
+* [unstable]  testbin
+Removing project succeeded!
diff --git a/test/build-server.multi_dist1/build-svr2-09.testcase b/test/build-server.multi_dist1/build-svr2-09.testcase
new file mode 100644 (file)
index 0000000..7c4a92e
--- /dev/null
@@ -0,0 +1,12 @@
+#PRE-EXEC
+#EXEC
+../../build-svr lock-dist -n testserver3 -D unstable
+../../build-svr lock-dist -n testserver3 -D unstable2
+../../build-svr unlock-dist -n testserver3 -D unstable
+../../build-svr unlock-dist -n testserver3 -D unstable2
+#POST-EXEC
+#EXPECT
+Distribution is locked!
+Locking distribution failed!
+Distribution is unlocked!
+Unlocking distribution failed!
diff --git a/test/build-server.multi_dist1/testsuite b/test/build-server.multi_dist1/testsuite
new file mode 100644 (file)
index 0000000..3f955a6
--- /dev/null
@@ -0,0 +1,9 @@
+build-svr2-01.testcase
+build-svr2-02.testcase
+build-svr2-03.testcase
+build-svr2-04.testcase
+build-svr2-05.testcase
+build-svr2-06.testcase
+build-svr2-07.testcase
+build-svr2-08.testcase
+build-svr2-09.testcase
diff --git a/test/build-server.multi_dist2/build-svr3-01.testcase b/test/build-server.multi_dist2/build-svr3-01.testcase
new file mode 100644 (file)
index 0000000..224c40a
--- /dev/null
@@ -0,0 +1,14 @@
+#PRE-EXEC
+#EXEC
+../../build-svr register -n testserver3 -D unstable -P bin/bin_0.0.0_ubuntu-32.zip
+#POST-EXEC
+#EXPECT
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for REGISTER Job
+Info: New Job
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
diff --git a/test/build-server.multi_dist2/build-svr3-02.testcase b/test/build-server.multi_dist2/build-svr3-02.testcase
new file mode 100644 (file)
index 0000000..b25a3de
--- /dev/null
@@ -0,0 +1,56 @@
+#PRE-EXEC
+#EXEC
+../../build-cli build  -N testa -d 127.0.0.1:2223 -D unstable
+../../build-cli build  -N testa -d 127.0.0.1:2223 -D unstable2
+#POST-EXEC
+#EXPECT
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Checking build dependency ...
+Info: Checking install dependency ...
+Info: Started to build this job...
+Info: JobBuilder
+Info: Downloding client is initializing...
+Info: Installing dependent packages...
+Info: Downloading dependent source packages...
+Info: Make clean...
+Info: Make build...
+Info: Make install...
+Info: Generatiing pkginfo.manifest...
+Info: Zipping...
+Info: Creating package file ... a_0.0.1_ubuntu-32.zip
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "testa"
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Checking build dependency ...
+Info: Checking install dependency ...
+Info: Started to build this job...
+Info: JobBuilder
+Info: Downloding client is initializing...
+Info: Installing dependent packages...
+Info: Downloading dependent source packages...
+Info: Make clean...
+Info: Make build...
+Info: Make install...
+Info: Generatiing pkginfo.manifest...
+Info: Zipping...
+Info: Creating package file ... a_0.0.1_ubuntu-32.zip
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "testa"
diff --git a/test/build-server.multi_dist2/build-svr3-03.testcase b/test/build-server.multi_dist2/build-svr3-03.testcase
new file mode 100644 (file)
index 0000000..be7df44
--- /dev/null
@@ -0,0 +1,28 @@
+#PRE-EXEC
+#EXEC
+../../build-cli register -d 127.0.0.1:2223 -P bin/bin_0.0.0_ubuntu-32.zip -D unstable2 -t ftp://ftpuser:ftpuser@127.0.0.1
+#POST-EXEC
+#EXPECT
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+I, [
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for REGISTER Job
+Info: New Job
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
diff --git a/test/build-server.multi_dist2/build-svr3-04.testcase b/test/build-server.multi_dist2/build-svr3-04.testcase
new file mode 100644 (file)
index 0000000..fe29a83
--- /dev/null
@@ -0,0 +1,18 @@
+#PRE-EXEC
+#EXEC
+../../build-svr fullbuild -n testserver3 -D unstable2
+#POST-EXEC
+#EXPECT
+Info: Initializing job...
+Info: Invoking a thread for MULTI-BUILD Job
+Info: New Job
+Info: Added new job "testa" for ubuntu-32!
+Info: Added new job "testb" for ubuntu-32!
+Info:  * Sub-Job "testa(ubuntu-32)" has entered "WORKING" state.
+Info:  * Sub-Job "testa(ubuntu-32)" has entered "FINISHED" state.
+Info:  * Sub-Job "testb(ubuntu-32)" has entered "WORKING" state.
+Info:  * Sub-Job "testb(ubuntu-32)" has entered "FINISHED" state.
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed
diff --git a/test/build-server.multi_dist2/build-svr3-05.testcase b/test/build-server.multi_dist2/build-svr3-05.testcase
new file mode 100644 (file)
index 0000000..6836515
--- /dev/null
@@ -0,0 +1,46 @@
+#PRE-EXEC
+../../pkg-svr remove-pkg -n pkgsvr01 -d unstable2 -P b
+#EXEC
+echo "=="
+../../build-svr lock-dist -n testserver3 -D unstable2
+echo "=="
+../../build-cli build -N testb -d 127.0.0.1:2223 -D unstable2
+echo "=="
+../../build-svr unlock-dist -n testserver3 -D unstable2
+echo "=="
+../../build-cli build -N testb -d 127.0.0.1:2223 -D unstable2
+#POST-EXEC
+#EXPECT
+==
+Distribution is locked!
+==
+Error: Distribution locked!: unstable2
+==
+Distribution is unlocked!
+==
+Info: Added new job
+Info: Initializing job...
+Info: Checking package version ...
+Info: Invoking a thread for building Job
+Info: New Job
+Info: Checking build dependency ...
+Info: Checking install dependency ...
+Info: Started to build this job...
+Info: JobBuilder
+Info: Downloding client is initializing...
+Info: Installing dependent packages...
+Info:  * a
+Info: Downloading dependent source packages...
+Info: Make clean...
+Info: Make build...
+Info: Make install...
+Info: Generatiing pkginfo.manifest...
+Info: Zipping...
+Info: Creating package file ... b_0.0.1_ubuntu-32.zip
+Info: Checking reverse build dependency ...
+Info: Uploading ...
+Info: Upload succeeded. Sync local pkg-server again...
+Info: Snapshot:
+Info: Job is completed!
+Info: Job is FINISHED successfully!
+Info: Updating the source info for project "testb"
diff --git a/test/build-server.multi_dist2/buildsvr.init b/test/build-server.multi_dist2/buildsvr.init
new file mode 100755 (executable)
index 0000000..5d4bc03
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+
+if [ ! "$DB_PASSWD" ] ; then
+       read -p "Insert DB password: " input
+       export DB_PASSWD=$input
+else
+       echo $DB_PASSWD
+fi
+
+rm -rf buildsvr01
+rm -rf git01
+rm -rf bin
+rm -rf ~/.build_tools/build_server/testserver3
+
+../../build-svr remove -n testserver3
+mkdir buildsvr01
+cd buildsvr01
+${RUBY} ../../../build-svr create -n testserver3 -t ftp://ftpuser:ftpuser@127.0.0.1
+echo "DROP DATABASE testserver3;" > a
+mysql -u root -p --password=$DB_PASSWD -h localhost < a
+${RUBY} ../../../build-svr migrate -n testserver3 --dsn Mysql:testserver3:localhost --dbuser root --dbpassword $DB_PASSWD
+rm -f a
+cd ..
+
+${RUBY} ../../build-svr add-dist -n testserver3 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333
+${RUBY} ../../build-svr add-dist -n testserver3 -D unstable2 -u `pwd`/pkgsvr01/unstable2 -d 127.0.0.1:3333
+${RUBY} ../../build-svr add-os -n testserver3 -o ubuntu-32
+${RUBY} ../../build-svr add-prj -n testserver3 -N testa -g `pwd`/git01/a -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testb -g `pwd`/git01/b -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testa -D unstable2 -g `pwd`/git01/a -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testb -D unstable2 -g `pwd`/git01/b -b master
+${RUBY} ../../build-svr add-prj -n testserver3 -N testbin -D unstable -P bin
+${RUBY} ../../build-svr add-prj -n testserver3 -N testbin -D unstable2 -P bin
+
+mkdir -p git01
+cp ../git01/*.tar.gz git01/
+cd git01
+rm -rf a
+rm -rf b
+tar xf a_v1.tar.gz
+tar xf b_v1.tar.gz
+cd ..
+
+mkdir -p bin
+cp ../bin/* bin/
+
+${RUBY}  ../../build-svr start -n testserver3 -p 2223 --CHILD
diff --git a/test/build-server.multi_dist2/pkgsvr.init b/test/build-server.multi_dist2/pkgsvr.init
new file mode 100755 (executable)
index 0000000..adfa33b
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+rm -rf ~/.build_tools/pkg_server/pkgsvr01
+rm -rf `pwd`/pkgsvr01
+${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable
+${RUBY} ../../pkg-svr add-dist -n pkgsvr01 -d unstable2
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o windows-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable2 -o ubuntu-32
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable2 -o windows-32
+${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333
diff --git a/test/build-server.multi_dist2/testsuite b/test/build-server.multi_dist2/testsuite
new file mode 100644 (file)
index 0000000..9f25506
--- /dev/null
@@ -0,0 +1,5 @@
+build-svr3-01.testcase
+build-svr3-02.testcase
+build-svr3-03.testcase
+build-svr3-04.testcase
+build-svr3-05.testcase
diff --git a/test/git01/a.tar.gz b/test/git01/a.tar.gz
new file mode 100644 (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
diff --git a/test/packageserver.testsuite b/test/packageserver.testsuite
new file mode 100644 (file)
index 0000000..7fe78d7
--- /dev/null
@@ -0,0 +1,22 @@
+packageserver01.testcase
+packageserver02.testcase
+packageserver24.testcase
+packageserver03.testcase
+packageserver04.testcase
+packageserver05.testcase
+packageserver06.testcase
+packageserver07.testcase
+packageserver08.testcase
+packageserver09.testcase
+packageserver11.testcase
+packageserver13.testcase
+packageserver14.testcase
+packageserver15.testcase
+packageserver16.testcase
+packageserver17.testcase
+packageserver18.testcase
+packageserver19.testcase
+packageserver20.testcase
+packageserver21.testcase
+packageserver22.testcase
+packageserver23.testcase
diff --git a/test/packageserver01.testcase b/test/packageserver01.testcase
new file mode 100644 (file)
index 0000000..f1c411e
--- /dev/null
@@ -0,0 +1,62 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr -h
+#POST-EXEC
+#EXPECT
+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
diff --git a/test/packageserver02.testcase b/test/packageserver02.testcase
new file mode 100644 (file)
index 0000000..408ca26
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+../pkg-svr remove -n temp_local --force
+#EXEC
+../pkg-svr create -n temp_local -d unstable 
+#POST-EXEC
+#EXPECT
+package server [temp_local] created successfully
diff --git a/test/packageserver03.testcase b/test/packageserver03.testcase
new file mode 100644 (file)
index 0000000..11eb774
--- /dev/null
@@ -0,0 +1,8 @@
+#PRE-EXEC
+../pkg-svr remove -n temp_remote --force
+#EXEC
+../pkg-svr create -n temp_remote -d unstable -u http://172.21.111.177/tmppkgsvr/tmp
+#POST-EXEC
+#EXPECT
+snapshot is generated : 
+package server [temp_remote] created successfully
diff --git a/test/packageserver04.testcase b/test/packageserver04.testcase
new file mode 100644 (file)
index 0000000..3be6257
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+../pkg-svr remove -n temp_remote_dup --force
+#EXEC
+../pkg-svr create -n temp_remote_dup -d unstable -u temp_remote/unstable
+#POST-EXEC
+#EXPECT
+package server [temp_remote_dup] created successfully
diff --git a/test/packageserver05.testcase b/test/packageserver05.testcase
new file mode 100644 (file)
index 0000000..da0ad18
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr add-dist -n temp_local -d stable 
+#POST-EXEC
+#EXPECT
+distribution [stable] added successfully
diff --git a/test/packageserver06.testcase b/test/packageserver06.testcase
new file mode 100644 (file)
index 0000000..cf49f46
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr sync -n temp_remote -d unstable 
+#POST-EXEC
+#EXPECT
+package server [temp_remote]'s distribution [unstable] has been synchronized.
diff --git a/test/packageserver07.testcase b/test/packageserver07.testcase
new file mode 100644 (file)
index 0000000..13bec0c
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr sync -n temp_remote_dup -d unstable --force
+#POST-EXEC
+#EXPECT
+package server [temp_remote_dup]'s distribution [unstable] has been synchronized.
diff --git a/test/packageserver08.testcase b/test/packageserver08.testcase
new file mode 100644 (file)
index 0000000..db9a935
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr gen-snapshot        -n temp_remote -s snap01
+#POST-EXEC
+#EXPECT
+snapshot is generated : 
diff --git a/test/packageserver09.testcase b/test/packageserver09.testcase
new file mode 100644 (file)
index 0000000..d8632bf
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s snap02
+#POST-EXEC
+#EXPECT
+snapshot is generated : 
diff --git a/test/packageserver10.testcase b/test/packageserver10.testcase
new file mode 100644 (file)
index 0000000..7a5fcb2
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s test
+#POST-EXEC
+#EXPECT
+snapshot is generated : 
diff --git a/test/packageserver11.testcase b/test/packageserver11.testcase
new file mode 100644 (file)
index 0000000..247141f
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s snap03 -b snap01
+#POST-EXEC
+#EXPECT
+snapshot is generated : 
diff --git a/test/packageserver12.testcase b/test/packageserver12.testcase
new file mode 100644 (file)
index 0000000..092eb4e
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s test3
+#POST-EXEC
+#EXPECT
+snapshot is generated : 
diff --git a/test/packageserver13.testcase b/test/packageserver13.testcase
new file mode 100644 (file)
index 0000000..ae8c629
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr create -n temp_remote_snap -d unstable -u temp_remote/unstable/snapshots/snap01
+#POST-EXEC
+#EXPECT
+package server [temp_remote_snap] created successfully
diff --git a/test/packageserver14.testcase b/test/packageserver14.testcase
new file mode 100644 (file)
index 0000000..06bdd06
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+cp test_server_pkg_file/smart-build-interface* ./
+#EXEC
+../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen
+#POST-EXEC
+#EXPECT
+package registed successfully
diff --git a/test/packageserver15.testcase b/test/packageserver15.testcase
new file mode 100644 (file)
index 0000000..af34b96
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen
+#POST-EXEC
+#EXPECT
+existing package's version is higher than register package
diff --git a/test/packageserver16.testcase b/test/packageserver16.testcase
new file mode 100644 (file)
index 0000000..4d09776
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+cp test_server_pkg_file/smart-build-interface* ./
+#EXEC
+../pkg-svr register -n temp_remote_dup -d unstable -P ./temp_remote/unstable/binary/smart-build-interface_1.20.1_linux.zip --gen --test
+#POST-EXEC
+#EXPECT
+package registed successfully
diff --git a/test/packageserver17.testcase b/test/packageserver17.testcase
new file mode 100644 (file)
index 0000000..ad1549b
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+cp test_server_pkg_file/smart-build-interface* ./
+#EXEC
+../pkg-svr remove-pkg -n temp_local -d unstable -P smart-build-interface
+#POST-EXEC
+#EXPECT
+package removed successfully
diff --git a/test/packageserver18.testcase b/test/packageserver18.testcase
new file mode 100644 (file)
index 0000000..431b64d
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+cp test_server_pkg_file/smart-build-interface* ./
+#EXEC
+../pkg-svr list
+#POST-EXEC
+#EXPECT 
+temp_remote_snap
diff --git a/test/packageserver19.testcase b/test/packageserver19.testcase
new file mode 100644 (file)
index 0000000..cd5b36b
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr list -n temp_local
+#POST-EXEC 
+rm smart-build-interface_1.20.1*
+#EXPECT 
+unstable
diff --git a/test/packageserver20.testcase b/test/packageserver20.testcase
new file mode 100644 (file)
index 0000000..7d47e52
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr remove -n temp_local --force
+#POST-EXEC 
+YES
+#EXPECT
+package server [temp_local] removed successfully
diff --git a/test/packageserver21.testcase b/test/packageserver21.testcase
new file mode 100644 (file)
index 0000000..1ae0b53
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr remove -n temp_remote --force
+#POST-EXEC 
+YES
+#EXPECT
+package server [temp_remote] removed successfully
diff --git a/test/packageserver22.testcase b/test/packageserver22.testcase
new file mode 100644 (file)
index 0000000..3dad192
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr remove -n temp_remote_dup --force
+#POST-EXEC 
+YES
+#EXPECT
+package server [temp_remote_dup] removed successfully
diff --git a/test/packageserver23.testcase b/test/packageserver23.testcase
new file mode 100644 (file)
index 0000000..6e37f2f
--- /dev/null
@@ -0,0 +1,7 @@
+#PRE-EXEC
+#EXEC
+../pkg-svr remove -n temp_remote_snap --force
+#POST-EXEC 
+YES
+#EXPECT
+package server [temp_remote_snap] removed successfully
diff --git a/test/packageserver24.testcase b/test/packageserver24.testcase
new file mode 100644 (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
diff --git a/test/pkg-cli-checkupgrade.testcase b/test/pkg-cli-checkupgrade.testcase
new file mode 100644 (file)
index 0000000..f9a19be
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01
+../pkg-cli check-upgrade -l pkgcli01 -u http://172.21.111.132/testserver2/unstable
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+"base-ide-product" package : 0.20.8 ->
+Info: Checked packages for upgrading.. OK
diff --git a/test/pkg-cli-clean-f.testcase b/test/pkg-cli-clean-f.testcase
new file mode 100644 (file)
index 0000000..fd4543d
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -t -l pkgcli01
+../pkg-cli clean -l pkgcli01 -f
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+Info: There is no any package.
diff --git a/test/pkg-cli-download-t.testcase b/test/pkg-cli-download-t.testcase
new file mode 100644 (file)
index 0000000..6d7263b
--- /dev/null
@@ -0,0 +1,13 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli download -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -t -l pkgcli01
+ls pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product_0.20.8_linux.zip
+common-eplugin_0.20.6_linux.zip
+nativeapp-eplugin_0.20.4_linux.zip
+nativecommon-eplugin_0.20.1_linux.zip
diff --git a/test/pkg-cli-download.testcase b/test/pkg-cli-download.testcase
new file mode 100644 (file)
index 0000000..f4e41d1
--- /dev/null
@@ -0,0 +1,10 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+cd pkgcli01; ../../pkg-cli download -p base-ide-product -u http://172.21.111.132/testserver3/unstable
+ls pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product_1.0.2_linux.zip
diff --git a/test/pkg-cli-install-f.testcase b/test/pkg-cli-install-f.testcase
new file mode 100644 (file)
index 0000000..7794646
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver2/unstable -l pkgcli01
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01 -f
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.8)
diff --git a/test/pkg-cli-install-t.testcase b/test/pkg-cli-install-t.testcase
new file mode 100644 (file)
index 0000000..00d2734
--- /dev/null
@@ -0,0 +1,13 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -t -l pkgcli01
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.8)
+common-eplugin  (0.20.6)
+nativeapp-eplugin  (0.20.4)
+nativecommon-eplugin  (0.20.1)
diff --git a/test/pkg-cli-install.testcase b/test/pkg-cli-install.testcase
new file mode 100644 (file)
index 0000000..31ac836
--- /dev/null
@@ -0,0 +1,10 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.8)
diff --git a/test/pkg-cli-installfile-f.testcase b/test/pkg-cli-installfile-f.testcase
new file mode 100644 (file)
index 0000000..810ad2f
--- /dev/null
@@ -0,0 +1,13 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver2/unstable -l pkgcli01
+../pkg-cli download -p base-ide-product -u http://172.21.111.132/testserver3/unstable
+../pkg-cli install-file -p base-ide-product_0.20.8_linux.zip -l pkgcli01 -f
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -f base-ide-product_0.20.8_linux.zip
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.8)
diff --git a/test/pkg-cli-installfile.testcase b/test/pkg-cli-installfile.testcase
new file mode 100644 (file)
index 0000000..ebdb5de
--- /dev/null
@@ -0,0 +1,12 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli download -p base-ide-product -u http://172.21.111.132/testserver3/unstable
+../pkg-cli install-file -p base-ide-product_0.20.8_linux.zip -l pkgcli01
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -f base-ide-product_0.20.8_linux.zip
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.8)
diff --git a/test/pkg-cli-listlpkg.testcase b/test/pkg-cli-listlpkg.testcase
new file mode 100644 (file)
index 0000000..31ac836
--- /dev/null
@@ -0,0 +1,10 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.8)
diff --git a/test/pkg-cli-listrpkg.testcase b/test/pkg-cli-listrpkg.testcase
new file mode 100644 (file)
index 0000000..84bf751
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-cli list-rpkg -u http://172.21.111.132/testserver3/unstable
+#POST-EXEC
+#EXPECT
+base-ide-product  (1.0.2)
diff --git a/test/pkg-cli-showlpkg.testcase b/test/pkg-cli-showlpkg.testcase
new file mode 100644 (file)
index 0000000..dbee48c
--- /dev/null
@@ -0,0 +1,12 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01
+../pkg-cli show-lpkg -p base-ide-product -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+Package : base-ide-product
+Version : 0.20.8
+OS : linux
diff --git a/test/pkg-cli-showrpkg.testcase b/test/pkg-cli-showrpkg.testcase
new file mode 100644 (file)
index 0000000..fc5cf62
--- /dev/null
@@ -0,0 +1,8 @@
+#PRE-EXEC
+#EXEC
+../pkg-cli show-rpkg -p base-ide-product -u http://172.21.111.132/testserver3/unstable
+#POST-EXEC
+#EXPECT
+Package : base-ide-product
+Version : 1.0.2
+OS : linux
diff --git a/test/pkg-cli-source.testcase b/test/pkg-cli-source.testcase
new file mode 100644 (file)
index 0000000..64053ad
--- /dev/null
@@ -0,0 +1,10 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+cd pkgcli01; ../../pkg-cli source -p base-ide-product -u http://172.21.111.132/testserver3/unstable
+ls pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+product_0.20.8.tar.gz
diff --git a/test/pkg-cli-uninstall-t.testcase b/test/pkg-cli-uninstall-t.testcase
new file mode 100644 (file)
index 0000000..749815f
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p nativeapp-eplugin -u http://172.21.111.132/testserver3/unstable -l pkgcli01 -t
+../pkg-cli uninstall -p base-ide-product -l pkgcli01 -t
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+Info: There is no any package.
diff --git a/test/pkg-cli-uninstall.testcase b/test/pkg-cli-uninstall.testcase
new file mode 100644 (file)
index 0000000..10e7647
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product - http://172.21.111.132/testserver3/unstable -l pkgcli01
+../pkg-cli uninstall -p base-ide-product -l pkgcli01
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+Info: There is no any package.
diff --git a/test/pkg-cli-update.testcase b/test/pkg-cli-update.testcase
new file mode 100644 (file)
index 0000000..3c6fa52
--- /dev/null
@@ -0,0 +1,6 @@
+#PRE-EXEC
+#EXEC
+../pkg-cli update -u http://172.21.111.132/testserver3/unstable
+#POST-EXEC
+#EXPECT
+Update package list from "http://172.21.111.132/testserver3/unstable".. OK
diff --git a/test/pkg-cli-upgrade.testcase b/test/pkg-cli-upgrade.testcase
new file mode 100644 (file)
index 0000000..493d947
--- /dev/null
@@ -0,0 +1,11 @@
+#PRE-EXEC
+rm -rf pkgcli01
+mkdir pkgcli01
+#EXEC
+../pkg-cli install -p base-ide-product -u http://172.21.111.132/testserver3/unstable -l pkgcli01
+../pkg-cli upgrade -l pkgcli01 -u http://172.21.111.132/testserver2/unstable
+../pkg-cli list-lpkg -l pkgcli01
+#POST-EXEC
+rm -rf pkgcli01
+#EXPECT
+base-ide-product  (0.20.14)
diff --git a/test/pkg-cli.testsuite b/test/pkg-cli.testsuite
new file mode 100644 (file)
index 0000000..21c2fe0
--- /dev/null
@@ -0,0 +1,18 @@
+pkg-cli-update.testcase
+pkg-cli-listrpkg.testcase
+pkg-cli-showrpkg.testcase
+pkg-cli-download.testcase
+pkg-cli-download-t.testcase
+pkg-cli-source.testcase
+pkg-cli-install.testcase
+pkg-cli-install-t.testcase
+pkg-cli-install-f.testcase
+pkg-cli-uninstall.testcase
+pkg-cli-uninstall-t.testcase
+pkg-cli-installfile.testcase
+pkg-cli-installfile-f.testcase
+pkg-cli-listlpkg.testcase
+pkg-cli-showlpkg.testcase
+pkg-cli-checkupgrade.testcase
+pkg-cli-upgrade.testcase
+pkg-cli-clean-f.testcase
index cf646288b6dfb5efea8a1c7a123310f01d300b9b..55d5272dff0845966966975b3ef6bbecfdf8eb43 100644 (file)
@@ -1,24 +1,40 @@
-Package : A
+Source : Origin
 Version : 0.1.0
+Maintainer : taejun.ha <tajun.ha@samsung.com>
+
+Package : A
 OS : linux
+C-test : test
 Build-host-os :linux | windows | darwin
-Maintainer : taejun.ha <tajun.ha@samsung.com>
 Path : binary/A_0.1.0_linux.zip
+C-commic : ask
 Origin : remote
-SHA256 : 52b400554f2a29dec46144af649181cf287c000b4feb65de72055ed9f11924a9
+C-origin : kkk
+Description : this is my first 
+script
+#Changes : kkk 
+#sa;ldfkj
+#alsdkfj
+#lsdkfj
 
 Package: B
-Version : 0.2.0
 OS : linux
 Build-host-os :linux | windows | darwin
-Maintainer : taejun.ha <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 : 
-Source : Origin
-From-server? : true
 SHA256 : your_checksum
 Description : this is my first 
-project
-descriotion 
+script
+C-kim : oks 
+Change-log :
+* 0.1.0
+test
+       ttkk
+* 1.0.8
+Add change log function
+       pkginfo.manifest include "change log" section
+* 1.0.7
+dibs document change 
+       you can read dibs documents in ubuntu using PDF readeranges 
diff --git a/test/pkg-list-local b/test/pkg-list-local
new file mode 100644 (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 
index ebace22cc958cf5c2dc9dccf8f23c63ca3d30c2d..da69b2df746cc041948e20235a2b46b874ff6410 100644 (file)
@@ -5,14 +5,17 @@ Build-host-os:linux | windows | darwin
 Maintainer : your_name <name@domain> name <name@domain>
 Install-dependency : codecoverage, rootstrap-slp-device-1.0, slp-ide
 Build-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221), scratchbox-aquila-simulator-rootstrap (>=    1.0.0.20101221), scratchbox-core (>= 1.0.17)
-Build-src-dependency : scratchbox-aquila-device-rootstrap   (>=     1.0.0.20101221)     [linux|windows], scratchbox-aquila-simulator-rootstrap [    linux   |windows    ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17)
+#Build-src-dependency : scratchbox-aquila-device-rootstrap   (>=     1.0.0.20101221)     [linux|windows], scratchbox-aquila-simulator-rootstrap [    linux   |windows    ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17)
 Description : this is my first 
+project that 
+is my 
+preciuse
 project :
 descriotion :
 Attribute :
-Install-script :
-Remove-script :
-Category :
+#Install-script :
+#Remove-script :
+#Category :
 Conflicts :
 Source : origin
 
@@ -23,13 +26,15 @@ Build-host-os:linux | windows | darwin
 Maintainer : your_name <name@domain> name <name@domain>
 Install-dependency : codecoverage, rootstrap-slp-device-1.0, slp-ide
 Build-dependency : scratchbox-aquila-device-rootstrap (>= 1.0.0.20101221), scratchbox-aquila-simulator-rootstrap (>=    1.0.0.20101221), scratchbox-core (>= 1.0.17)
-Build-src-dependency : scratchbox-aquila-device-rootstrap   (>=     1.0.0.20101221)     [linux|windows], scratchbox-aquila-simulator-rootstrap [    linux   |windows    ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17)
+Source-dependency : scratchbox-aquila-simulator-rootstrap [    linux   |windows    ](>= 1.0.0.20101221), scratchbox-core [windows|darwin](>= 1.0.17)
 Description : this is my first 
+hello
+project
 project :
 descriotion :
 Attribute :
-Install-script :
-Remove-script :
-Category :
+C-ategory :
+#Install-script :
+#Remove-script :
 Conflicts :
 Source : origin
diff --git a/test/pkgsvr2.init b/test/pkgsvr2.init
new file mode 100755 (executable)
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
diff --git a/test/regression.rb b/test/regression.rb
new file mode 100755 (executable)
index 0000000..11aa893
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/ruby
+$success_cases=[]
+$failure_cases=[]
+$testcases=[]
+
+$total_cnt = 0
+
+testCaseName = ""
+resultCheck = ""
+resultFlag = ""
+resultCmdCount = 0
+
+
+class TestCase
+       attr_accessor :name, :pre_exec_cmds, :exec_cmds, :post_exec_cmds, :expected_results
+       def initialize(name)
+               @name = name
+               @pre_exec_cmds = []
+               @exec_cmds = []
+               @post_exec_cmds = []
+               @expected_results = []
+       end
+
+       def is_succeeded?(results)
+               i = 0
+               @expected_results.each do |e|
+                       found = false
+                       if results[i].nil? then
+                               return false
+                       end
+                       if not results[i].include? e then
+                               return false
+                       end
+                       i += 1
+               end     
+
+               return true
+       end
+end
+
+
+# parse
+def parse_testcase(file_name)
+       # create
+       tcase = TestCase.new( file_name )
+
+       # parse
+       File.open(file_name,"r") do |f|
+               status="START"
+               f.each_line do |l|
+                       ln = l.strip
+                       if ln == "#PRE-EXEC" or ln == "#EXEC"  or 
+                               ln == "#POST-EXEC" or ln == "#EXPECT" then
+
+                               status = ln
+                       else
+                               case status
+                               when "#PRE-EXEC"
+                                       tcase.pre_exec_cmds.push ln                     
+                               when "#EXEC"
+                                       tcase.exec_cmds.push ln                 
+                               when "#POST-EXEC"
+                                       tcase.post_exec_cmds.push ln                    
+                               when "#EXPECT"
+                                       tcase.expected_results.push ln                  
+                               else
+                                       # ignore
+                               end
+                       end
+               end
+       end
+
+       return tcase    
+end
+
+
+# test execution
+def execute( file_name )
+       printf("#{file_name} ... ")
+       STDOUT.flush
+
+       # parse
+       tcase = parse_testcase( file_name )
+
+       # pre-exec
+       tcase.pre_exec_cmds.each do |cmd|
+               fork_p = false
+               if cmd[-1,1] == "&" then
+                       cmd = cmd[0..-2]
+                       fork_p = true   
+               end
+
+               # get result
+               if not fork_p then
+                       IO.popen("#{cmd} 2>&1") { |io|
+               #               io.each do |line|
+               #                       puts "---> #{line}"
+               #               end
+                       }
+               else
+                       IO.popen("#{cmd} 2>&1 &") { |io|
+               #               io.each do |line|
+               #                       puts "---> #{line}"
+               #               end
+                       }
+               end
+               #`#{cmd}`
+       end     
+
+       # exec
+       results = []
+       tcase.exec_cmds.each do |cmd|
+               fork_p = false
+               hidden_p = false
+               if cmd[-1,1] == "&" then
+                       cmd = cmd[0..-2]
+                       fork_p = true   
+               end
+               if cmd[0,1] == ">" then
+                       cmd = cmd[1..-1]
+                       hidden_p = true 
+               end
+               # get result
+               if fork_p then
+                       IO.popen("#{cmd} 2>&1 &") { |io|
+                               io.each do |line|
+                                       if not hidden_p then
+                                               results.push line.strip
+                                       #puts "---> #{line}"
+                                       end
+                               end
+                       }
+               else
+                       IO.popen("#{cmd} 2>&1") { |io|
+                               io.each do |line|
+                                       if not hidden_p then
+                                               results.push line.strip
+                                       #puts "---> #{line}"
+                                       end
+                               end
+                       }
+               end
+       end
+
+       # check expected result
+       if tcase.is_succeeded?(results) then
+               puts "SUCCESS"
+               $success_cases.push file_name
+       else    
+       puts "FAIL"
+               $failure_cases.push file_name
+               results.each do |l|
+                       puts ">" + l
+               end
+       end
+
+       # post-exec
+       tcase.post_exec_cmds.each do |cmd|
+               # get result
+               IO.popen("#{cmd} 2>&1") { |io|
+               }
+               #`#{cmd}`
+       end
+end
+
+
+#test_list file open
+if (ARGV.size() == 0)
+  testsuite_name = "list.txt"
+else
+  testsuite_name = ARGV.shift
+end
+
+# execute testsuite
+puts
+puts "Regression Test Start      "
+puts "=================================="
+
+File.open( testsuite_name ) do |f|
+       f.each_line do |line|
+       $testcases.push("#{line.strip}")
+               execute(line.strip)
+    end
+end
+
+# print result 
+puts
+puts "Regression Test Result"
+puts "----------------------"
+puts "Total Test Case : #{$testcases.count}"
+puts "Test Success    : #{$success_cases.count}"
+puts "Test Errors     : #{$failure_cases.count}"
+puts
+
+if $failure_cases.count != 0 then
+    puts "Test Fail Files"
+    puts "---------------"
+    $failure_cases.each do |name|
+        puts name
+    end 
+    puts
+end
+
diff --git a/test/test.sh b/test/test.sh
new file mode 100755 (executable)
index 0000000..e765f43
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+./regression.rb pkg-cli.testsuite
+./regression.rb packageserver.testsuite
+./regression.rb buildserver.testsuite
+./regression.rb buildcli.testsuite
index c299f7f388b2b659dc9369c81a53612c948afd2a..0c11ace089e0b50cf1220d64331f1c59cfd232cd 100755 (executable)
@@ -2,8 +2,9 @@
 require '../src/common/parser'
 require '../src/common/package'
 
-alist = Parser.read_pkg_list "pkg-list"
-a_list = alist.values
-a_list.each do |l|
+alist = Parser.read_multy_pkginfo_from "pkg-list"
+alist.each do |l|
     l.print
-end 
+       puts l.change_log_string
+       puts ""
+end
index 64bdb77caf758dff89e43787b0d9472bc6d85afe..c3f18a0ce30d84c29faa00277825d5eb0d961509 100755 (executable)
@@ -1,65 +1,66 @@
 #!/bin/sh 
 
 echo "============ remove 1 =============="
-../pkg-svr remove -i temp_local
+../pkg-svr remove -n temp_local --force
 echo "============ remove 2 =============="
-../pkg-svr remove -i temp_remote
+../pkg-svr remove -n temp_remote --force
 echo "============ remove 3 =============="
-../pkg-svr remove -i temp_remote_dup
+../pkg-svr remove -n temp_remote_dup --force
 echo "============ remove 4 =============="
-../pkg-svr remove -i temp_remote_snap
+../pkg-svr remove -n temp_remote_snap --force
 echo "============ create 1 =============="
-../pkg-svr create -i temp_local -d unstable 
+../pkg-svr create -n temp_local -d unstable 
 echo "============ create 2 =============="
-../pkg-svr create -i temp_remote -d unstable -u http://172.21.17.55/pkgserver/unstable 
+../pkg-svr create -n temp_remote -d unstable -u http://172.21.17.55/private/develop
 echo "============ create 3 =============="
-../pkg-svr create -i temp_remote_dup -d unstable -u temp_remote/unstable
+../pkg-svr create -n temp_remote_dup -d unstable -u temp_local/unstable
 echo "============ add dist 1 =============="
-../pkg-svr add-dist -i temp_local -d stable 
+../pkg-svr add-dist -n temp_local -d stable 
 echo "============ sync 1 =============="
-../pkg-svr sync -i temp_remote -d unstable 
+../pkg-svr sync -n temp_remote -d unstable 
 echo "============ sync 2 =============="
-../pkg-svr sync -i temp_remote_dup -d unstable -f
+../pkg-svr sync -n temp_remote_dup -d unstable --force
 echo "============ gen snapshot 1 =============="
-../pkg-svr gen-snapshot        -i temp_remote
+../pkg-svr gen-snapshot        -n temp_remote
 echo "============ gen snapshot 2 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable 
+../pkg-svr gen-snapshot -n temp_remote -d unstable 
 echo "============ gen snapshot 3 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -n test
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s test
 echo "============ gen snapshot 4 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -n test2 -b test 
+../pkg-svr gen-snapshot -n temp_remote -d unstable -s test2 -b test 
 echo "============ gen snapshot 5 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -o linux
+../pkg-svr gen-snapshot -n temp_remote -d unstable -o linux
 echo "============ gen snapshot 6 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -o windows
+../pkg-svr gen-snapshot -n temp_remote -d unstable -o windows
 echo "============ gen snapshot 7 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -o darwin
+../pkg-svr gen-snapshot -n temp_remote -d unstable -o darwin
 echo "============ gen snapshot 8 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -o all 
+../pkg-svr gen-snapshot -n temp_remote -d unstable -o all 
 echo "============ gen snapshot 9 =============="
-../pkg-svr gen-snapshot -i temp_remote -d unstable -o all -p test_server_pkg_file/smart-build-interface_1.20.1_linux.zip -n test3
+../pkg-svr gen-snapshot -n temp_remote -d unstable -o all -P test_server_pkg_file/smart-build-interface_1.20.1_linux.zip -s test3
 echo "============ create 4 =============="
-../pkg-svr create -i temp_remote_snap -d unstable -u temp_remote/unstable/snapshots/test
+../pkg-svr create -n temp_remote_snap -d unstable -u temp_remote/unstable/snapshots/test
 echo "============ register 1 =============="
-cp test_server_pkg_file/smart-build-interface_1.20.1_linux.zip ./smart-build-interface_1.20.1_linux.zip 
-cp test_server_pkg_file/smart-build-interface_1.20.1.tar.gz ./smart-build-interface_1.20.1.tar.gz
-../pkg-svr register -i temp_remote -d unstable -p smart-build-interface_1.20.1_linux.zip -s smart-build-interface_1.20.1.tar.gz -g
-echo "============ spkg path 1 =============="
-../pkg-svr spkg-path -i temp_remote -d unstable -s smart-build-interface_1.20.1.tar.gz
+cp test_server_pkg_file/smart-build-interface_*_linux.zip ./
+../pkg-svr register -n temp_local -d unstable -P smart-build-interface_1.20.1_linux.zip
 echo "============ register 2 =============="
-cp test_server_pkg_file/smart-build-interface_1.20.1_linux.zip ./smart-build-interface_1.20.1_linux.zip 
-cp test_server_pkg_file/smart-build-interface_1.20.1.tar.gz ./smart-build-interface_1.20.1.tar.gz
-../pkg-svr register -i temp_remote -d unstable -p smart-build-interface_1.20.1_linux.zip -s smart-build-interface_1.20.1.tar.gz -g
+cp test_server_pkg_file/smart-build-interface_*_linux.zip ./
+../pkg-svr register -n temp_remote -d unstable -P smart-build-interface_1.20.1_linux.zip --gen
 echo "============ register 3 =============="
-../pkg-svr register -i temp_remote_dup -d unstable -p ./temp_remote/unstable/binary/smart-build-interface_1.20.1_linux.zip -s ./temp_remote/unstable/source/smart-build-interface_1.20.1.tar.gz -g -t
+cp test_server_pkg_file/smart-build-interface_*_linux.zip ./
+../pkg-svr register -n temp_remote_dup -d unstable -P smart-build-interface_1.20.1_linux.zip --gen --test
+echo "============ register 4 =============="
+cp test_server_pkg_file/archive.zip ./
+../pkg-svr register -n temp_local -d unstable -A archive.zip
 echo "============ remove 3 ==============" 
-../pkg-svr remove-pkg -i temp_remote_dup -d unstable -p smart-build-interface
+../pkg-svr remove-pkg -n temp_local -d unstable -P smart-build-interface
+echo "============ clean 1 ==============" 
+../pkg-svr clean -n temp_local -d unstable 
+echo "============ clean 2 ==============" 
+../pkg-svr clean -n temp_remote -d unstable -s test,test2,test3 
 echo "============ list 1 =============="
 ../pkg-svr list
 echo "============ list 2 =============="
-../pkg-svr list -i temp_local
-#../pkg-svr remove -i temp
+../pkg-svr list -n temp_local
+#../pkg-svr remove -n temp
 
-#cleanup
-rm smart-build-interface_1.20.1_linux.zip 
-rm smart-build-interface_1.20.1.tar.gz
diff --git a/test/test_server_pkg_file/archive.zip b/test/test_server_pkg_file/archive.zip
new file mode 100644 (file)
index 0000000..140bd05
Binary files /dev/null and b/test/test_server_pkg_file/archive.zip 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
diff --git a/test/upgrade/01.testcase b/test/upgrade/01.testcase
new file mode 100644 (file)
index 0000000..af117a1
--- /dev/null
@@ -0,0 +1,9 @@
+#PRE-EXEC
+./dibs1/build-svr upgrade -n testserver3 -D unstable
+#EXEC
+sleep 3
+ls dibs1/VERSION dibs2/VERSION
+#POST-EXEC
+#EXPECT
+dibs1/VERSION
+dibs2/VERSION
diff --git a/test/upgrade/buildsvr1.init b/test/upgrade/buildsvr1.init
new file mode 100755 (executable)
index 0000000..0578b61
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+CURDIR=`pwd`
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby "
+fi
+
+rm -rf buildsvr01
+rm -rf git01
+rm -rf bin
+rm -rf ~/.build_tools/build_server/testserver3
+rm -rf dibs1
+mkdir dibs1
+cp -r ../../src dibs1/
+cp -r ../../build-svr dibs1/
+cp -r ../../pkg-svr dibs1/
+cp -r ../../upgrade dibs1/
+cd ../../
+./pkg-build -u $CURDIR/pkgsvr01/unstable
+cd $CURDIR
+
+dibs1/build-svr remove -n testserver3
+mkdir buildsvr01
+cd buildsvr01
+${RUBY} ../dibs1/build-svr create -n testserver3
+${RUBY} ../dibs1/build-svr migrate -n testserver3
+cd ..
+
+${RUBY} dibs1/build-svr add-dist -n testserver3 -D unstable -u $CURDIR/pkgsvr01/unstable -d 127.0.0.1:3333
+${RUBY} dibs1/build-svr add-svr -n testserver3 -d 127.0.0.1:2224
+${RUBY} dibs1/build-svr add-os -n testserver3 -o ubuntu-32
+${RUBY} dibs1/pkg-svr register -n pkgsvr01 -d unstable -P ../../dibs_*.zip
+
+${RUBY} dibs1/build-svr start -n testserver3 -p 2223
+
diff --git a/test/upgrade/buildsvr2.init b/test/upgrade/buildsvr2.init
new file mode 100755 (executable)
index 0000000..ac5ccf7
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby "
+fi
+
+rm -rf buildsvr02
+rm -rf dibs2
+mkdir dibs2
+cp -r ../../src dibs2/
+cp -r ../../build-svr dibs2/
+cp -r ../../pkg-svr dibs2/
+cp -r ../../upgrade dibs2/
+
+../../build-svr remove -n testserver4
+mkdir buildsvr02
+cd buildsvr02
+${RUBY} ../dibs2/build-svr create -n testserver4
+${RUBY} ../dibs2/build-svr migrate -n testserver4
+cd ..
+${RUBY} dibs2/build-svr add-dist -n testserver4 -D unstable -u `pwd`/pkgsvr01/unstable -d 127.0.0.1:3333
+
+${RUBY} dibs2/build-svr start -n testserver4 -p 2224
diff --git a/test/upgrade/pkgsvr.init b/test/upgrade/pkgsvr.init
new file mode 100755 (executable)
index 0000000..d0c7cd9
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+if [ "x${RUBY}" = "x" ] ;then
+    RUBY="ruby -d"
+fi
+rm -rf ~/.build_tools/pkg_server/pkgsvr01
+rm -rf `pwd`/pkgsvr01
+${RUBY} ../../pkg-svr create -n pkgsvr01 -d unstable
+${RUBY} ../../pkg-svr add-os -n pkgsvr01 -d unstable -o ubuntu-32
+${RUBY} ../../pkg-svr start -n pkgsvr01 -p 3333
diff --git a/test/upgrade/testsuite b/test/upgrade/testsuite
new file mode 100644 (file)
index 0000000..1bb2eb2
--- /dev/null
@@ -0,0 +1 @@
+01.testcase
diff --git a/tizen-ide/get_ide_sources.sh b/tizen-ide/get_ide_sources.sh
new file mode 100755 (executable)
index 0000000..b7c58d9
--- /dev/null
@@ -0,0 +1,276 @@
+#!/bin/bash
+
+###############################################################
+## Variables
+###############################################################
+
+START_PATH=~+  ## like `pwd`
+SCRIPT_NAME=$0
+SCRIPT_OPERATION=$1
+ARG1=$2
+ARG2=$3
+ARG3=$4
+GIT_PORT=29419
+CONTINUE=n
+GIT_LIST="
+/sdk/ide/common-eplugin
+/sdk/ide/eventinjector-eplugin
+/sdk/ide/nativecommon-eplugin
+/sdk/ide/nativeappcommon-eplugin
+/sdk/ide/native-eplugin
+/sdk/ide/native-ext-eplugin
+/sdk/ide/native-sample
+/sdk/ide/nativeplatform-eplugin
+/sdk/ide/unittest-eplugin
+/sdk/ide/profiler-eplugin
+/sdk/ide/codecoverage-eplugin
+/sdk/ide/assignmenttracing-eplugin
+/sdk/ide/webapp-eplugin
+/sdk/ide/product
+/sdk/ide/websimulator-eplugin
+/sdk/tools/sdb
+"
+# /sdk/ide/nativeapp-eplugin
+# /sdk/ide/native-gui-builder-eplugin
+# /sdk/gui-builder/native-gui-builder
+# /sdk/ide/telephony-eplugin
+# /sdk/ide/codehiding-eplugin
+
+###############################################################
+## Usage output functions
+###############################################################
+
+function usage() {
+       echo "Usage : ${SCRIPT_NAME##*/} <command> [<args>]"; echo
+       echo "The most commonly used script commands are :"
+       echo "  clone           Clone git sources about Tizen SDK"
+       echo "  pull            Pull git sources about Tizen SDK"
+       echo "  checkout        checkout git sources about Tizen SDK"; echo
+       exit 1
+}
+
+function usage_pull() {
+       echo "Usage : ${SCRIPT_NAME##*/} pull : Git pull in current directory";
+       echo "Usage : ${SCRIPT_NAME##*/} pull <source directory> : Git pull in source directory";
+
+       draw_line
+       echo "  Ex1) \$ ${SCRIPT_NAME} pull"; echo
+       echo "  Ex2) \$ ${SCRIPT_NAME} pull $(pwd)/tizen-ide-sources"; echo
+       exit 1
+}
+
+function usage_checkout() {
+       echo "Usage : ${SCRIPT_NAME##*/} checkout <branch name> : Git checkout in current directory";
+       echo "Usage : ${SCRIPT_NAME##*/} checkout <branch name> <source directory> : Git checkout in source directory";
+
+       draw_line
+       echo "  Ex1) \$ ${SCRIPT_NAME} checkout develop"; echo
+       echo "  Ex2) \$ ${SCRIPT_NAME} checkout develop $(pwd)/tizen-ide-sources"; echo
+       exit 1
+}
+
+function usage_clone() {
+       draw_line
+       echo "Usage : 1) ${SCRIPT_NAME##*/} clone <git branch name> <host> : Git clone in curreut directory"; echo
+       echo "        2) ${SCRIPT_NAME##*/} clone <git branch name> <host> <destination directory>: Git clone in destination directory"
+       draw_line
+       echo "  Ex1) \$ ${SCRIPT_NAME} clone develop gerrithost"
+       echo "  Ex2) \$ ${SCRIPT_NAME} clone release http://develop.tizen.org/git:2039 /home/usr/work/git"
+       exit 1
+}
+
+
+###############################################################
+## Processing Functions
+###############################################################
+
+function draw_line() {
+       echo; echo "==========================================================================="; echo;
+}
+
+## Error Check Function
+function isError() {
+       ERROR_CODE=$?
+
+       if [ ${ERROR_CODE} == 0 ]; then
+               echo "[ $1 : Done ]"; 
+       else
+               echo "[ $1 : Fail (ErrorCode : ${ERROR_CODE}) ]"
+               if [ ${CONTINUE} == "n" ]; then
+                       input=0
+                       while [ ${input} != "y" -a ${input} != "n" -a ${input} != "a" ]; do
+                               echo "Continue? y: Yes, n: No, a: Yes to all"
+                               read input
+                               if [ ${input} == "n" ]; then
+                                       exit ${ERROR_CODE}
+                               elif [ ${input} == "a" ]; then
+                                       CONTINUE=y
+                                       echo ${CONTINUE}
+                               fi
+                       done
+               fi
+       fi
+}
+
+## Cloning git
+function git_clone() {
+       GIT_PATH=$1
+       GIT_NAME=${GIT_PATH##*/}
+
+       ## ARG1 : <git branch name>
+       ## ARG2 : <host>
+       ## ARG3 : <destination directory>
+       git clone -b ${ARG1} ${ARG2}:${GIT_PATH} ${ARG3}/${GIT_NAME}
+       isError "Cloned ${GIT_NAME}"
+       scp -p -P ${GIT_PORT} ${ARG2}:hooks/commit-msg ${ARG3}/${GIT_NAME}/.git/hooks/
+       isError "Generate change-id ${GIT_NAME}"
+}
+
+## Cloning git all
+function git_clone_all() {
+       draw_line; echo "Git clone sources"; draw_line
+
+       for GIT_EACH in ${GIT_LIST}
+       do
+               git_clone ${GIT_EACH}
+       done
+}
+
+## Pulling git
+function git_pull() {
+       GIT_PATH=$1
+       GIT_NAME=${GIT_PATH##*/}
+
+       ## ARG1 : <source directory>
+       cd ${ARG1}/${GIT_NAME}
+       isError "Found git directory ( ${ARG1}/${GIT_NAME} )"
+       git pull
+       isError "Pulled ${GIT_NAME}"
+}
+
+## Pulling git all
+function git_pull_all() {
+       draw_line;      echo "Git pull sources"; draw_line
+
+       cd ${ARG1}
+       isError "Checked source directory ( ${ARG1} )"
+
+       for GIT_EACH in ${GIT_LIST}
+       do
+               git_pull ${GIT_EACH}
+       done
+
+       cd ${START_PATH}
+}
+
+## Checking out git
+function git_checkout() {
+       GIT_PATH=$1
+       GIT_NAME=${GIT_PATH##*/}
+
+       ## ARG1 : <source directory>
+       cd ${ARG2}/${GIT_NAME}
+       isError "Found git directory ( ${ARG2}/${GIT_NAME} )"
+       git checkout ${ARG1}
+       isError "Checkout ${GIT_NAME}"
+}
+
+## Checking out git all
+function git_checkout_all() {
+       draw_line;      echo "Git checkout"; draw_line
+
+       cd ${ARG2}
+       isError "Checked source directory ( ${ARG1} )"
+
+       for GIT_EACH in ${GIT_LIST}
+       do
+               git_checkout ${GIT_EACH}
+       done
+
+       cd ${START_PATH}
+}
+
+## Command git
+function git_command() {
+       GIT_PATH=$1
+       GIT_NAME=${GIT_PATH##*/}
+
+       ## ARG1 : <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
+###############################################################
+
+case ${SCRIPT_OPERATION} in
+       ## process "clone" operation
+       clone)
+               if [ "$#" == 4 ]; then
+                       git_clone_all
+               elif [ "$#" == 3 ]; then
+                       ARG3=$(pwd)
+                       git_clone_all                   
+               else
+                       usage_clone
+               fi
+               ;;
+
+       ## process "pull" operation
+       pull)
+               if [ "$#" == 2 ]; then
+                       git_pull_all
+               elif [ "$#" == 1 ]; then
+                       ARG1=$(pwd)
+                       git_pull_all
+               else
+                       usage_pull
+               fi
+               ;;
+
+       ## process "checkout" operation
+       checkout)
+               if [ "$#" == 3 ]; then
+                       git_checkout_all
+               elif [ "$#" == 2 ]; then
+                       ARG2=$(pwd)
+                       git_checkout_all
+               else
+                       usage_checkout
+               fi
+               ;;
+
+       ## process default
+       *)
+               if [ "$#" == 1 ]; then
+                       ARG1=$(pwd)
+                       git_command_all
+               else
+                       usage
+               fi
+               ;;
+esac
+
+echo "[ Finished process ]"
+
+###############################################################
+## End script
+###############################################################
diff --git a/upgrade b/upgrade
new file mode 100755 (executable)
index 0000000..26120ad
--- /dev/null
+++ b/upgrade
@@ -0,0 +1,285 @@
+#!/usr/bin/ruby
+=begin
+
+ upgrade
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+Contact:
+Taejun Ha <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 "BuildServerController"
+require "utils.rb"
+require "log.rb"
+require "client"
+
+def option_error_check( options )
+       if options[:start] then
+       if options[:locate].nil? or options[:type].nil? or options[:name].nil? then
+                       raise ArgumentError, "upgrade -l <dibs path> -S -t <server type> -n <server name> -p <server port> -D <distribution name>" + "\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
+
+        opts.on( '-D', '--distribution <distribution name>', 'build server distribution name' ) do|dist|
+            options[:dist] = dist
+        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]
+       svr_dist = option[:dist]
+
+       DIBS_PKG_NAME = "dibs"
+       BACKUP_ROOT = Utils::HOME + "/.build_tools/backup"
+       PREV_VER_PATH = BACKUP_ROOT + "/prev_ver"
+       NEW_VER_PATH = BACKUP_ROOT + "/new_ver"
+       UPGRADE_CMD = "#{PREV_VER_PATH}/upgrade"
+       BUILD_CONFIG_ROOT = "#{Utils::HOME}/.build_tools/build_server/#{svr_name}"
+
+       if not svr_dist.nil? then
+               build_server = BuildServerController.get_server(svr_name)
+               dist = build_server.distmgr.get_distribution(svr_dist)
+               if dist.nil? then
+                       log.error "Upgrade failed : No distribution name \"#{svr_dist}\" exist!", Log::LV_USER
+                       cmd = Utils.generate_shell_command("#{dibs_path}/build-svr start -n #{svr_name} -p #{svr_port}")
+                       Utils.spawn(cmd)
+                       exit 1
+               end
+       end
+
+       if not File.exist? BACKUP_ROOT then FileUtils.mkdir_p(BACKUP_ROOT) end
+       log = StandardOutLog.new( "#{BUILD_CONFIG_ROOT}/log" )
+
+       if not install_opt then
+               puts ""
+               log.info("Upgrade Start...", Log::LV_USER)
+
+               # Backup current dibs
+               if File.exist? PREV_VER_PATH then FileUtils.rm_rf(PREV_VER_PATH) end
+               if File.exist? NEW_VER_PATH then FileUtils.rm_rf(NEW_VER_PATH) end
+               FileUtils.mkdir_p(PREV_VER_PATH)
+               FileUtils.mkdir_p(NEW_VER_PATH)
+               FileUtils.cp_r("#{dibs_path}/.", PREV_VER_PATH, :preserve => true)
+               log.info("Backup DIBS [#{dibs_path}] -> [#{PREV_VER_PATH}]", Log::LV_USER)
+
+               # Run Upgrade
+               if start_opt and svr_type.eql? "BUILDSERVER"  then
+                       cmd = "#{UPGRADE_CMD} -I -l #{dibs_path} -S -t #{svr_type} -n #{svr_name} -p #{svr_port}"
+
+                       if not (pkg_svr_url.nil? or pkg_svr_url.empty?) then
+                               cmd += " -u #{pkg_svr_url}"
+                       end
+
+                       if not (svr_dist.nil? or svr_dist.empty?) then
+                               cmd += " -D #{svr_dist}"
+                       end
+
+               else
+                       cmd = "#{UPGRADE_CMD} -I -l #{dibs_path} -u #{pkg_svr_url}"
+               end
+
+               cmd = Utils.generate_shell_command(cmd)
+               Utils.spawn(cmd)
+
+       else
+               # Get SERVER INFORMATION
+               if start_opt and svr_type.eql? "BUILDSERVER" then
+                       # only when acesss build server controller
+                       build_server = BuildServerController.get_server(svr_name)
+                       if pkg_svr_url.nil? or pkg_svr_url.empty? then
+                               if svr_dist.nil? or svr_dist.empty? then
+                                       pkg_svr_url = build_server.distmgr.get_default_pkgsvr_url()
+                               else
+                                       dist = build_server.distmgr.get_distribution(svr_dist)
+                                       if not dist.nil? then
+                                               pkg_svr_url = dist.pkgsvr_url
+                                       else
+                                               log.error "Upgrade failed : No distribution name \"#{svr_dist}\" exist!", Log::LV_USER
+                                               exit 1
+                                       end
+                               end
+                       end
+                       log.info("Build server : [#{svr_name}][#{svr_port}]", Log::LV_USER)
+               end
+               log.info("Package Server : [#{pkg_svr_url}]", Log::LV_USER)
+               log.info("DIBS Path : [#{dibs_path}]", Log::LV_USER)
+
+               # Download DIBS Package
+       client = Client.new( pkg_svr_url, NEW_VER_PATH, log)
+       client.update()
+               client.install( DIBS_PKG_NAME, Utils::HOST_OS, true, true)
+
+               # Copy Current path
+               if File.exist? "#{dibs_path}" then
+                       FileUtils.rm_rf("#{dibs_path}")
+                       #FileUtils.mkdir_p("#{dibs_path}")
+               end
+               if File.exist? "#{NEW_VER_PATH}/tools/dibs" then
+                       FileUtils.cp_r("#{NEW_VER_PATH}/tools/dibs/.", "#{dibs_path}", :preserve => true)
+               else
+                       log.error("Not installed package error.", Log::LV_USER)
+                       exit(1)
+               end
+
+               # Execute start command
+               if start_opt
+                       if not build_server.nil? and svr_type.eql? "BUILDSERVER" then
+                               # get friends server information
+                               build_server.get_remote_servers().each do |svr|
+                                       ip = svr.ip
+                                       port = svr.port
+
+                                       build_client = BuildCommClient.create( ip, port )
+                                       if build_client.nil? then
+                                               log.info("Friend Server #{ip}:#{port} is not running!", Log::LV_USER)
+                                               next
+                                       end
+
+                                       # send request
+                                       log.info("Upgrading Friend Server #{ip}:#{port}...", Log::LV_USER)
+                                       if build_client.send "UPGRADE|#{build_server.password}" then
+                                               # recevie & print
+                                               mismatched = false
+                                               result = build_client.read_lines do |l|
+                                                       log.info(l, Log::LV_USER)
+                                                       if l.include? "Password mismatched!" then
+                                                               mismatched = true
+                                                       end
+                                               end
+                                               if not result then
+                                                       log.info("Upgrading failed! #{build_client.get_error_msg()}", Log::LV_USER)
+                                               elsif mismatched then
+                                                       log.info("Upgrading failed! Password mismatched!", Log::LV_USER)
+                                               end
+                                       else
+                                               log.info("Upgrading failed! #{build_client.get_error_msg()}", Log::LV_USER)
+                                               next
+                                       end
+
+                                       # terminate
+                                       build_client.terminate
+                               end
+
+                               # Start Build server
+                               cmd = Utils.generate_shell_command("#{dibs_path}/build-svr start -n #{svr_name} -p #{svr_port}")
+                               Utils.spawn(cmd)
+
+                               log.info("Upgrade Complete", Log::LV_USER)
+                               log.info("Start Build server [#{cmd}]", Log::LV_USER)
+
+                       else # PACKAGE SERVER
+                               # Start Build server
+                               cmd = Utils.generate_shell_command("#{dibs_path}/pkg-svr start -n #{svr_name} -p #{svr_port}")
+                               Utils.spawn(cmd)
+
+                               log.info("Upgrade Complete", Log::LV_USER)
+                               log.info("Start Package server [#{cmd}]", Log::LV_USER)
+                       end
+               else
+                       log.info("Upgrade Complete", Log::LV_USER)
+               end
+       end
+rescue => e
+       log.error(e.message, Log::LV_USER)
+       #puts e.message
+end
+