From cf6cbbe3fbdb923f8f10269afd7296d96fea0249 Mon Sep 17 00:00:00 2001 From: "jonghwan2.park" Date: Mon, 27 Jan 2014 16:36:42 +0900 Subject: [PATCH] DIBS: Added -x option Build cli command line tool can make sdk image with exception package list. Change-Id: I43083583aaf8d03af1217de51e31a34a6ce0bb87 Signed-off-by: jonghwan2.park --- package/changelog | 3 + package/pkginfo.manifest | 4 +- pkg-cli | 349 ++- src/pkg_server/client.rb | 4052 +++++++++++++++-------------- src/pkg_server/clientOptParser.rb | 475 ++-- 5 files changed, 2510 insertions(+), 2373 deletions(-) diff --git a/package/changelog b/package/changelog index 5221be2..0b76b16 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,6 @@ +* 2.1.58 +- Added make-image option [-x] for except packages +== jonghwan park 2014-01-27 * 2.1.57 - Fixed marshar error bug and some minor bugs == donghee yang 2014-01-23 diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index c7d4c03..a127315 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,6 +1,6 @@ Source : dibs -Version :2.1.57 -Maintainer : taejun ha, jiil hyoun , donghyuk yang , donghee yang , sungmin kim , jiil hyoun , donghyuk yang , donghee yang , sungmin kim Package : tizen-dibs-test Label : DIBS Test Tools diff --git a/pkg-cli b/pkg-cli index b524f30..f82b80c 100755 --- a/pkg-cli +++ b/pkg-cli @@ -44,210 +44,209 @@ require "packageServer" #option parsing begin - option = option_parse + option = option_parse rescue => e - # if option parse error print help message - puts e.message - exit 0 + # if option parse error print help message + puts e.message + exit 0 end # check HOST OS if not Utils.check_host_OS() then - if Utils.is_linux_like_os Utils::HOST_OS then - Utils.set_default_linux_host_os - puts "Warning: Your host OS is not supported!\nWe assume your host OS as #{Utils::HOST_OS} !!!" - else - puts "Error: Your host OS is not supported!" - exit 1 - end + if Utils.is_linux_like_os Utils::HOST_OS then + Utils.set_default_linux_host_os + puts "Warning: Your host OS is not supported!\nWe assume your host OS as #{Utils::HOST_OS} !!!" + else + puts "Error: Your host OS is not supported!" + exit 1 + end end #if "--os" is not specfied, use host os type if option[:os].nil? then - option[:os] = Utils::HOST_OS + option[:os] = Utils::HOST_OS end case option[:cmd] when "clean" then - client = Client.create( nil, option[:loc], nil, false ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.clean(option[:f]) + client = Client.create( nil, option[:loc], nil, false ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.clean(option[:f]) when "download" then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - file_loc = client.download( option[:pkg], option[:os], option[:t] ) + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + file_loc = client.download( option[:pkg], option[:os], option[:t] ) when "make-img" then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.make_img( option[:os], option[:info] ) + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.make_img( option[:os], option[:info], option[:el] ) when "dep-graph" then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.gen_dep_graph( option[:os], option[:type] ) + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.gen_dep_graph( option[:os], option[:type] ) when "install" then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.install( option[:pkg], option[:os], option[:t], option[:f] ) + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.install( option[:pkg], option[:os], option[:t], option[:f] ) when "install-file" then - if option[:t] then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.install_local_pkg( option[:pkg], option[:t], option[:f] ) - else - client = Client.create( nil, option[:loc], nil, false ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.install_local_pkg( option[:pkg], option[:t], option[:f] ) - end + if option[:t] then + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.install_local_pkg( option[:pkg], option[:t], option[:f] ) + else + client = Client.create( nil, option[:loc], nil, false ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.install_local_pkg( option[:pkg], option[:t], option[:f] ) + end when "uninstall" then - client = Client.create( nil, option[:loc], nil, false ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.uninstall( option[:pkg], option[:t] ) + client = Client.create( nil, option[:loc], nil, false ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.uninstall( option[:pkg], option[:t] ) when "upgrade" then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.upgrade( option[:os], option[:t] ) + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.upgrade( option[:os], option[:t] ) when "check-upgrade" then - client = Client.create( option[:url], option[:loc], nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.check_upgrade( option[:os] ) + client = Client.create( option[:url], option[:loc], nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.check_upgrade( option[:os] ) when "show-rpkg" then - client = Client.create( option[:url], nil, nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - puts client.show_pkg_info( option[:pkg], option[:os] ) + client = Client.create( option[:url], nil, nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + puts client.show_pkg_info( option[:pkg], option[:os] ) when "list-rpkg" then - client = Client.create( option[:url], nil, nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - 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 + client = Client.create( option[:url], nil, nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + 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 when "show-lpkg" then - client = Client.create( nil, option[:loc], nil, false ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - puts client.show_installed_pkg_info( option[:pkg] ) + client = Client.create( nil, option[:loc], nil, false ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + puts client.show_installed_pkg_info( option[:pkg] ) when "list-lpkg" then - client = Client.create( nil, option[:loc], nil, false ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - 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 - else - puts "Info: There is no any package." - end + client = Client.create( nil, option[:loc], nil, false ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + 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 + else + puts "Info: There is no any package." + end when "build-dep" then - client = Client.create( option[:url], nil, nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - result = client.get_build_dependent_packages( option[:pkg], option[:os], true ) - if result.nil? then - puts "Error: Failed to get remote package list. try update first." - exit 1 - end - ret = "" - result.each do |i| - ret = ret + i + " --> " - end - ret = ret.strip - ret[-3..-1] = "" - puts ret + client = Client.create( option[:url], nil, nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + result = client.get_build_dependent_packages( option[:pkg], option[:os], true ) + if result.nil? then + puts "Error: Failed to get remote package list. try update first." + exit 1 + end + ret = "" + result.each do |i| + ret = ret + i + " --> " + end + ret = ret.strip + ret[-3..-1] = "" + puts ret when "install-dep" then - client = Client.create( option[:url], nil, nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - result = client.get_install_dependent_packages( option[:pkg], option[:os], true, false ) - if result.nil? then - puts "Error: Failed to get remote package list. try update first." - exit 1 - end - ret = "" - result.each do |i| - ret = ret + i + " --> " - end - ret = ret.strip - ret[-3..-1] = "" - puts ret + client = Client.create( option[:url], nil, nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + result = client.get_install_dependent_packages( option[:pkg], option[:os], true, false ) + if result.nil? then + puts "Error: Failed to get remote package list. try update first." + exit 1 + end + ret = "" + result.each do |i| + ret = ret + i + " --> " + end + ret = ret.strip + ret[-3..-1] = "" + puts ret when "register" then - client = Client.create( nil, nil, nil ) - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.register(option[:address], option[:dist], option[:pkg], option[:passwd]) + client = Client.create( nil, nil, nil ) + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.register(option[:address], option[:dist], option[:pkg], option[:passwd]) when "snapshotlist" then - client = Client.create(option[:url],nil,nil); - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - client.printSnapshotList(option[:all]); + client = Client.create(option[:url],nil,nil); + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + client.printSnapshotList(option[:all]); when "changelog" then - client = Client.create(option[:url], nil, nil); - if client.nil? then - puts "Error: Cannot create package client!" - exit 1 - end - if option[:snapshot].nil?() then - client.printChangeLog(); - else - client.printChangeLog(option[:snapshot][0], option[:snapshot][1]); - end + client = Client.create(option[:url], nil, nil); + if client.nil? then + puts "Error: Cannot create package client!" + exit 1 + end + if option[:snapshot].nil?() then + client.printChangeLog(); + else + client.printChangeLog(option[:snapshot][0], option[:snapshot][1]); + end else - raise RuntimeError, "Input is incorrect : #{option[:cmd]}" + raise RuntimeError, "Input is incorrect : #{option[:cmd]}" end - diff --git a/src/pkg_server/client.rb b/src/pkg_server/client.rb index 0007fa5..b4b5749 100644 --- a/src/pkg_server/client.rb +++ b/src/pkg_server/client.rb @@ -54,335 +54,335 @@ $get_snapshot_mutex = Mutex.new $cache_mutex = Mutex.new class Client - # 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 - private_class_method :new - - 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, access_svr = true) - - # 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 location - if location.nil? then location = get_default_inst_dir() end - - @location = location - @snapshot_path = nil - @snapshot_url = false - @pkg_hash_os = {} - @installed_pkg_hash_loc = {} - @archive_pkg_list = [] - @all_dep_list = [] - @support_os_list = [] - @server_addr = nil - - - # if client should access remote server, set server information - if access_svr then - if not server_addr.nil? then - # chop server address, if end with "/" - if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end - server_addr.strip! - - 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 - @is_server_remote = Utils.is_url_remote(server_addr) - @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 - end - end - - @configs = {} - #default cache size = 8G - @configs[:CACHE_SIZE] = "8000" - end - - - public - def self.create(server_addr, location, logger, access_svr = true) - new_client = new(server_addr, location, logger, access_svr ) - if new_client.init(access_svr) then - return new_client - else - return nil - end - end - - - public - def init(access_svr) - if access_svr then - # read remote pkg list, and hash list - @log.info "Update remote package list and supported os list.." - if update() then - @log.info "Initialize - #{@server_addr}, #{@location}" - else - @log.error "Failed to update remote package list." - return false - end - 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() - - return true - end - - - # make cache clean - private - def remove_old_files_in_cache - #get dir info - cache_list = get_cache_dir_list - cache_info_list = Utils.get_sub_files_info(cache_list).sort {|a,b| a[3] <=> b[3]} # [path,size,ctime,mtime] - cache_size = 0 - cache_info_list.each {|file| cache_size += file[1]} - - read_configs - max_cache_size = get_config_max_cache_size - - extra_size = cache_size - max_cache_size - - if extra_size < 0 then return end - - remove_list = [] - while extra_size > 0 do - old_package = cache_info_list.shift - remove_list.push old_package[0] - extra_size -= old_package[1] - end - - if not remove_list.empty? then - @log.info "Removed oldest package files.. (Now not fully caching)" - @log.info " * #{remove_list.map{|path| File.basename(path)}.join(", ")}" - FileUtils.rm_rf remove_list - end - end - - private - def get_cache_dir_list - return Dir.entries(CONFIG_PATH).select{|dir| not dir.start_with? "." and File.directory? CONFIG_PATH + "/#{dir}/downloads" }.map{|dir| CONFIG_PATH + "/#{dir}/downloads"} - end - - private - def get_config_max_cache_size - return (@configs[:CACHE_SIZE] =~ /^([0-9][0-9]*)$/i)? ($1.to_i * 1024 * 1024) : (8 * 1024 * 1024 * 1024) #default size 4G : unit = MB - end - - private - def read_configs - file_path = CONFIG_PATH + "/config" - if not File.exist? file_path then return end - - File.open file_path, "r" do |f| - f.each_line do |l| - row = l.split(":") - @configs[row[0].strip.to_sym] = row[1..-1].join(":").strip - end - end - end - - - public - # update package list from server - def update() - - if @server_addr.nil? then - @log.warn "Server address is null" - return false - end - - 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 - - @log.info "Update package list from \"#{@server_addr}\".. OK" - - 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. Check if it exist in package server" - return nil - end - url = surl + pkg_path - filename = File.basename pkg_path - - file_path = get_file_from_cache(filename, pkg_checksum, pkg_size, loc) - if file_path.nil? then - - file_path = File.join(loc, filename) - - result = FileDownLoader.download(url, loc, @log) - if not result or not File.exist? file_path then - @log.error "File Download Failed!!" - @log.error "* #{url} -> #{loc}" - return nil - end - - if Utils.validatePkgFile(file_path, pkg_checksum, pkg_size) then - add_file_to_cache(file_path) - else - @log.error "File Validation Failed!!" - @log.info "Valiate : file path : #{file_path}, shasum : #{pkg_checksum}, size : #{pkg_size}", Log::LV_USER - return nil - end - else - @log.info "Cached #{pkg_name} package file.. OK" - end - 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 + # 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 + private_class_method :new + + 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, access_svr = true) + + # 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 location + if location.nil? then location = get_default_inst_dir() end + + @location = location + @snapshot_path = nil + @snapshot_url = false + @pkg_hash_os = {} + @installed_pkg_hash_loc = {} + @archive_pkg_list = [] + @all_dep_list = [] + @support_os_list = [] + @server_addr = nil + + + # if client should access remote server, set server information + if access_svr then + if not server_addr.nil? then + # chop server address, if end with "/" + if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end + server_addr.strip! + + 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 + @is_server_remote = Utils.is_url_remote(server_addr) + @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 + end + end + + @configs = {} + #default cache size = 8G + @configs[:CACHE_SIZE] = "8000" + end + + + public + def self.create(server_addr, location, logger, access_svr = true) + new_client = new(server_addr, location, logger, access_svr ) + if new_client.init(access_svr) then + return new_client + else + return nil + end + end + + + public + def init(access_svr) + if access_svr then + # read remote pkg list, and hash list + @log.info "Update remote package list and supported os list.." + if update() then + @log.info "Initialize - #{@server_addr}, #{@location}" + else + @log.error "Failed to update remote package list." + return false + end + 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() + + return true + end + + + # make cache clean + private + def remove_old_files_in_cache + #get dir info + cache_list = get_cache_dir_list + cache_info_list = Utils.get_sub_files_info(cache_list).sort {|a,b| a[3] <=> b[3]} # [path,size,ctime,mtime] + cache_size = 0 + cache_info_list.each {|file| cache_size += file[1]} + + read_configs + max_cache_size = get_config_max_cache_size + + extra_size = cache_size - max_cache_size + + if extra_size < 0 then return end + + remove_list = [] + while extra_size > 0 do + old_package = cache_info_list.shift + remove_list.push old_package[0] + extra_size -= old_package[1] + end + + if not remove_list.empty? then + @log.info "Removed oldest package files.. (Now not fully caching)" + @log.info " * #{remove_list.map{|path| File.basename(path)}.join(", ")}" + FileUtils.rm_rf remove_list + end + end + + private + def get_cache_dir_list + return Dir.entries(CONFIG_PATH).select{|dir| not dir.start_with? "." and File.directory? CONFIG_PATH + "/#{dir}/downloads" }.map{|dir| CONFIG_PATH + "/#{dir}/downloads"} + end + + private + def get_config_max_cache_size + return (@configs[:CACHE_SIZE] =~ /^([0-9][0-9]*)$/i)? ($1.to_i * 1024 * 1024) : (8 * 1024 * 1024 * 1024) #default size 4G : unit = MB + end + + private + def read_configs + file_path = CONFIG_PATH + "/config" + if not File.exist? file_path then return end + + File.open file_path, "r" do |f| + f.each_line do |l| + row = l.split(":") + @configs[row[0].strip.to_sym] = row[1..-1].join(":").strip + end + end + end + + + public + # update package list from server + def update() + + if @server_addr.nil? then + @log.warn "Server address is null" + return false + end + + 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 + + @log.info "Update package list from \"#{@server_addr}\".. OK" + + 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. Check if it exist in package server" + return nil + end + url = surl + pkg_path + filename = File.basename pkg_path + + file_path = get_file_from_cache(filename, pkg_checksum, pkg_size, loc) + if file_path.nil? then + + file_path = File.join(loc, filename) + + result = FileDownLoader.download(url, loc, @log) + if not result or not File.exist? file_path then + @log.error "File Download Failed!!" + @log.error "* #{url} -> #{loc}" + return nil + end + + if Utils.validatePkgFile(file_path, pkg_checksum, pkg_size) then + add_file_to_cache(file_path) + else + @log.error "File Validation Failed!!" + @log.info "Valiate : file path : #{file_path}, shasum : #{pkg_checksum}, size : #{pkg_size}", Log::LV_USER + return nil + end + else + @log.info "Cached #{pkg_name} package file.. OK" + end + 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 public def gen_dep_graph(os, type) - if (os == "all") then + if (os == "all") then puts "==graph explain==" puts " box : package name" puts " red arrow : install dependency" puts " blue arrow : build dependency" puts "execute below graph generate command on your shell\n" - @support_os_list.each do |os| make_dep_graph(os, type) end - else + @support_os_list.each do |os| make_dep_graph(os, type) end + else if(@support_os_list.include? os) puts "execute below command on your shell\n" - make_dep_graph(os, type) + make_dep_graph(os, type) else @log.error "not support os name : #{os}\n server supports #{@support_os_list.join(',')}" end - end + end end def dot_ident(string) @@ -419,50 +419,102 @@ class Client puts "dot -Tpng -o #{type}_dep_#{os}.png #{type}_dep_#{os}.dot" end - public - def make_img(os, img_info) - if (os == "all") then - @support_os_list.each do |os| image_generator(os, img_info) end - else - image_generator(os, img_info) - end - end - - private - # make sdk image - def image_generator(os, img_info) - # get package list - all_pkg_list = @pkg_hash_os[os].values - - # select meta and install-type packages - img_pkg_list = [] - all_pkg_list.each { |pkg| - attr = get_attr_from_pkg(pkg.package_name, os, "attribute") - if attr.nil? or attr.empty? then next end - if attr[0].strip.upcase.eql? "ROOT" or attr[0].strip.upcase.eql? "INSTALL" then - dependent_pkg_list = get_install_dependent_packages(pkg.package_name, os, true, true) - img_pkg_list = img_pkg_list + dependent_pkg_list - end - } - img_pkg_list.uniq! - - # init workspace - workspace = @location+"/temp_for_tizen_sdk_imgs_#{os}" - if File.directory? workspace then FileUtils.remove_dir(workspace, true) end - - # download packages - img_pkg_list.each do |pkg| download(pkg, os, false, "#{workspace}/binary") end - - # write pkg_list_os file - FileUtils.cp("#{get_pkglist_path}/pkg_list_#{os}", "#{workspace}") - - # write os_info file - File.open("#{workspace}/#{OS_INFO_FILE}", 'w') do |f| f.puts os end + public + def make_img(os, img_info, remove_list = nil) + if (os == "all") then + @support_os_list.each { |os| image_generator(os, img_info, remove_list) } + else + image_generator(os, img_info, remove_list) + end + end + + private + # make sdk image + def image_generator(os, img_info, user_input_list) + # select meta and install-type packages + metapackage_list = [] + installtype_list = [] + @pkg_hash_os[os].values.each { |pkg| + attr = get_attr_from_pkg(pkg.package_name, os, "attribute") + if attr.nil? or attr.empty? then next end + if attr[0].strip.upcase.eql? "ROOT" or attr[0].strip.upcase.eql? "MANDATORY" then + metapackage_list.push(pkg.package_name) + elsif attr[0].strip.upcase.eql? "INSTALL" then + installtype_list.push(pkg.package_name) + end + } + + @log.info "<< Meta-Package List >>" + @log.info " - #{metapackage_list.sort}" + @log.info "<< Install Type Package List >>" + @log.info " - #{installtype_list}" + @log.info "" + + # validate user input + if user_input_list.empty? or user_input_list.nil? then + user_input_list = [] + else + user_input_list.each { |i| + flag = false + metapackage_list.each { |j| if "#{i}" == "#{j}" then flag = true end} + if flag == false then + @log.info "[#{i}] is not in package server. please check it (We are case-sensitive)." + return false + end + } + # get all meta-packages in user input + remove_metapackage_list = [] + user_input_list.each { |i| + get_install_dependent_packages(i, os, true, true).each { |j| + attr = get_attr_from_pkg(j, os, "attribute") + if attr.nil? or attr.empty? then next end + if attr[0].strip.upcase.eql? "ROOT" then + remove_metapackage_list.push(j) + end + } + } + @log.info "<< User Input List>>" + @log.info " - #{user_input_list}" + @log.info " - #{remove_metapackage_list}" + @log.info "" + end + + # get final package list + img_pkg_list = [] + if user_input_list.empty? then + metapackage_list.each { |pkg| + img_pkg_list = img_pkg_list + get_install_dependent_packages(pkg, os, true, true) + } + else + metapackage_list = metapackage_list - remove_metapackage_list + metapackage_list.each { |pkg| + img_pkg_list = img_pkg_list + get_install_dependent_packages_with_except(pkg, os, true, true, user_input_list) + } + end + + img_pkg_list.uniq! + img_pkg_list = img_pkg_list + installtype_list + @log.info "<< Final Package List >>" + @log.info " - #{img_pkg_list.sort}" + @log.info "" + + # init workspace + workspace = @location+"/temp_for_tizen_sdk_imgs_#{os}" + if File.directory? workspace then FileUtils.remove_dir(workspace, true) end + + # download packages + img_pkg_list.each do |pkg| download(pkg, os, false, "#{workspace}/binary") end + + # write pkg_list_os file + FileUtils.cp("#{get_pkglist_path}/pkg_list_#{os}", "#{workspace}") + + # write os_info file + File.open("#{workspace}/#{OS_INFO_FILE}", 'w') do |f| f.puts os end # set image.info message = ""; message = img_info; - + if message.to_s.eql? "" then server = @server_addr; origin = File.dirname( server ); @@ -473,1615 +525,1691 @@ class Client message.strip! server = message; origin = File.dirname( server ); - dist = File.basename( server ); - end + dist = File.basename( server ); + end # write image.info f = File.new("#{workspace}/image.info", "w"); f.write("origin : #{origin}\ndistribution : #{dist}\n"); f.close - # compress files - snapshot = snapshot_path.split('/')[-1] - img_name = "TIZEN-SDK-IMG_#{snapshot}_#{os}.zip" - cmd = "cd #{workspace}; zip -q -r #{@location}/TIZEN-SDK-IMG_#{snapshot_path.split('/')[-1]}_#{os}.zip *;" - Utils.execute_shell_with_log(cmd, @log.path) - - # clean workspace - FileUtils.remove_dir(workspace, true) - @log.info "<< SDK-Image Info. >>" - @log.info " - server addr : #{@server_addr}" - @log.info " - snapshot : #{snapshot}" - @log.info " - os : #{os}" - @log.info " - location : #{location}/" - @log.info " - name : #{img_name}" - - return - end - - private - def get_file_from_cache(filename, pkg_checksum, pkg_size, location) - if not File.directory? location then return nil end - downloaded_file_path = nil - @log.info "Wait for cache sync",Log::LV_USER - begin - lock = Utils.file_lock(File.join(CONFIG_PATH,".cache_lock")) - @log.info "Entering cache sync",Log::LV_USER - cached_filepath = get_cached_filepath(filename, pkg_checksum, pkg_size) - if not cached_filepath.nil? and File.exist? cached_filepath then - #FileUtils.ln(cached_filepath, location, :force => true) - if (FileUtil.safeLink(cached_filepath, location)) then - downloaded_file_path = File.join(location, File.basename(cached_filepath)) - end - end - ensure - Utils.file_unlock(lock) if not lock.nil? - end - @log.info "Cache sync done",Log::LV_USER - if not downloaded_file_path.nil? and not File.exist? downloaded_file_path then - downloaded_file_path = nil - end - return downloaded_file_path - end - - private - def add_file_to_cache(filepath) - if filepath.nil? or filepath.empty? or not File.exist? filepath then return end - if not File.exist? @download_path then FileUtils.mkdir_p "#{@download_path}" end - - filename = File.basename(filepath) - cachefile = File.join(@download_path, filename) - - @log.info "Moving \"#{filename}\" to download cache directory" - @log.info " [path: #{@download_path}]" - - if not File.exist? cachefile then - #FileUtils.ln(filepath, @download_path, :force => true) - if not FileUtil.safeLink(filepath, @download_path) then - @log.info "Failed to link file [#{filepath}] to " - @log.info " [#{@download_path}]" - end - end - - if not File.exist? cachefile then - @log.info "Failed to move [#{filename}] to " - @log.info " [#{@download_path}]" - end - - begin - lock = Utils.file_lock(File.join(CONFIG_PATH,".cache_lock")) - - remove_old_files_in_cache - ensure - Utils.file_unlock(lock) if not lock.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 - if Utils.validatePkgFile(cached_filepath, pkg_checksum, pkg_size) then - FileUtils.touch cached_filepath - return cached_filepath - else - return nil - 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 - - private - def upload_request(ip, port, dock, transporter, binary_path_list) - binary_path_list.each do |bpath| - client2 = BuildCommClient.create(ip, port, @log) - begin - if client2.nil? then - raise RuntimeError, "Failed to create BuildCommClient instance.." - end - - @log.info "Send UPLOAD REQ.. [UPLOAD|#{dock}]" - result = client2.send("UPLOAD|#{dock}") - if not result then - raise RuntimeError, "Failed to send ready REQ.." - end - result = client2.send_file(bpath, transporter) - ensure - client2.terminate - end - end - end - - public - # upload package - def upload(ip, port, binary_path_list, ftp_addr=nil, ftp_port=nil, ftp_username=nil, ftp_passwd=nil, password="") - - # 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 - - 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 - rescue => e - @log.error "FTP failed to put file (exception)" - @log.error "#{e.message}" - @log.error e.backtrace.inspect - return nil - end - - binary_list = [] - binary_path_list.each do |binary_path| - if File.exist? binary_path then - binary_list.push(File.basename(binary_path)) - else - @log.error "Binary file does not exist" - return nil - end - end - - client = BuildCommClient.create(ip, port, @log) - if client.nil? then - @log.error "Can't access server #{ip}:#{port}" - return nil - end - - begin - # create unique dock number - dock = Utils.create_uniq_name() - - dist = get_distribution - if dist.empty? then - @log.error "Distribution is empty.." - return nil - end - - @log.info "Send register message.. [REGISTER|#{dist}|#{password}|DOCK|#{dock}|#{binary_list.join("|")}]" - snapshot = nil - - client.send "REGISTER|#{dist}|#{password}|DOCK|#{dock}|#{binary_list.join("|")}" - - client.read_lines do |line| - if line.eql?("WAITFORUPLOAD") then - # upload - @log.info "Get WAITFORUPLOAD message" - thread = Thread.new do - begin - upload_request(ip, port, dock, transporter, binary_path_list) - rescue => e - puts "Transfering file failed!" - puts e.message - end - end - - thread.join - client.send("REGISTERCONTINUE") - elsif line.start_with? "SUCC" then - snapshot = line.split("|")[1] - elsif line.start_with? "ERROR" then - @log.error line.strip - return nil - else - @log.error "Unknown message received : #{l}" - end - end - ensure - client.terminate - end - - if not snapshot.nil? and not snapshot.empty? then - snapshot = @server_addr + "/snapshots/" + snapshot - @log.info "Registered successfully! [#{binary_path_list.join("|")}]" - if snapshot.empty? then - @log.error "Failed to generate snapshot" - end - - return snapshot - else - return nil - end - 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 - - @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) - - 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) - - pkg_name = Utils.get_package_name_from_package_file( pkg_path ) - pkg_os = Utils.get_os_from_package_file( pkg_path ) - - 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 "\"#{filename}\" 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 - pkg_conflicts = pkg.conflicts - 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 - - # TODO: Resolve conflicts - if not resolve_conflicts_internal(pkg_conflicts) then - @log.error "Failed to resolve conflicts [#{pkg_name}]" - return 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}." - 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 - # get default path for installing - def get_default_inst_dir() - return Dir.pwd - 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] - 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) - end - end - end - - return result - end - - public - # get reverse source dependent packages (just 1 depth) - 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 - # 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 - # 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 "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 - when "conflicts" then return pkg.conflicts - - 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 - def resolve_conflicts_internal(conflicts_pkgs) - if conflicts_pkgs.nil? then return true end - conflicts_pkgs.each do |pkg| - if check_installed_pkg(pkg.package_name) then - if not uninstall(pkg.package_name, true) then - @log.error "Failed to uninstall [#{pkg.package_name}] package for resolving" - return false - else - @log.info "Resolved conflict package [#{pkg.package_name}]" - end - end - end - return true - end - - private - def resolve_conflicts(pkg_name, os) - conflicts = get_attr_from_pkg(pkg_name, os, "conflicts") - return resolve_conflicts_internal(conflicts) - 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") - - # 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 - - # resolve conflict packages - if not resolve_conflicts(pkg_name, os) then - @log.error "Failed to resolve conflicts [#{pkg_name}]" - return false - end - - # install package - #download - tmp_location = nil - begin - tmp_location = File.join(@tmp_path,Utils.create_uniq_name) - filepath = download(pkg_name, os, false, tmp_location) - if filepath.nil? or filepath[0].nil? then - return false - end - - #install - ret = FileInstaller.install(pkg_name, filepath[0], type, @location, @log) - ensure - #remove garbage - FileUtils.rm_rf tmp_location if not tmp_location.nil? and File.exist? tmp_location - 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.error "Server does not have \"#{ssinfo_file}\" file." - return nil - end - else - if File.exist? file_url then - FileUtils.cp(file_url, @config_dist_path) - else - @log.error "Server does not have \"#{ssinfo_file}\" file." - return nil - 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? "ROOT" then return true - else return false end - end - - public - def register(address, distribution, pkg_file_path, password) - # check file exist - if not File.exist? pkg_file_path then - puts "The file does not exist!.. #{pkg_file_path}" - return false - end - - result = Utils.parse_server_addr(address) - if result.nil? then - puts "Server address is incorrect. (#{address})" - puts "Tune as following format." - puts " :" - exit 1 - end - bs_ip = result[0] - bs_port = result[1] - - pkg_file_path_list = [] - pkg_file_path_list.push(pkg_file_path) - # set distribution - @server_addr = distribution - ret = upload(bs_ip, bs_port, pkg_file_path_list, nil, nil, nil, nil, password) - - if ret then @log.info "Snapshot is generated : #{ret}" end - end - - ##Print change log to console. - public - def printChangeLog(snapshot1 = nil, snapshot2 = nil) - snapshotPath = File.join(@config_dist_path, PackageServerConstants::SNAPSHOT_INFO_FILE_NAME) - @log.info("Read information of snapshot from " + snapshotPath); - - ssController = SnapshotController.new(snapshotPath); - changeLogController = ChangeLogController.new(@server_addr, ssController) - - if (snapshot1.nil?()) then - changeLog = changeLogController.getLatestChangeLog(); - elsif snapshot2.nil?() then - changeLog = changeLogController.getChangeLog(snapshot1); - else - changeLog = changeLogController.getTotalChangeLog(snapshot1, snapshot2); - end - - puts changeLog - end - - ##Print snapshot list to console. - public - def printSnapshotList(showAll=false) - snapshotPath = File.join(@config_dist_path, PackageServerConstants::SNAPSHOT_INFO_FILE_NAME) - @log.info("Read information of snapshot from " + snapshotPath); - - ssController = SnapshotController.new(snapshotPath); - if showAll then - result = ssController.getAllSnapshotList; - else - result = ssController.getManualSnapshotList ; - end - - result.each() do |snapshot| - puts PackageServerConstants::SNAPSHOT_NAME_FIELD + ": " + snapshot.getName() - puts PackageServerConstants::SNAPSHOT_TIME_FIELD + ": " + snapshot.getTime() - puts - end - - end + # compress files + snapshot = snapshot_path.split('/')[-1] + img_name = "TIZEN-SDK-IMG_#{snapshot}_#{os}.zip" + cmd = "cd #{workspace}; zip -q -r #{@location}/TIZEN-SDK-IMG_#{snapshot_path.split('/')[-1]}_#{os}.zip *;" + Utils.execute_shell_with_log(cmd, @log.path) + + # clean workspace + FileUtils.remove_dir(workspace, true) + @log.info "<< SDK-Image Info. >>" + @log.info " - server addr : #{@server_addr}" + @log.info " - snapshot : #{snapshot}" + @log.info " - os : #{os}" + @log.info " - location : #{location}/" + @log.info " - name : #{img_name}" + + return + end + + private + def get_file_from_cache(filename, pkg_checksum, pkg_size, location) + if not File.directory? location then return nil end + downloaded_file_path = nil + @log.info "Wait for cache sync",Log::LV_USER + begin + lock = Utils.file_lock(File.join(CONFIG_PATH,".cache_lock")) + @log.info "Entering cache sync",Log::LV_USER + cached_filepath = get_cached_filepath(filename, pkg_checksum, pkg_size) + if not cached_filepath.nil? and File.exist? cached_filepath then + #FileUtils.ln(cached_filepath, location, :force => true) + if (FileUtil.safeLink(cached_filepath, location)) then + downloaded_file_path = File.join(location, File.basename(cached_filepath)) + end + end + ensure + Utils.file_unlock(lock) if not lock.nil? + end + @log.info "Cache sync done",Log::LV_USER + if not downloaded_file_path.nil? and not File.exist? downloaded_file_path then + downloaded_file_path = nil + end + return downloaded_file_path + end + + private + def add_file_to_cache(filepath) + if filepath.nil? or filepath.empty? or not File.exist? filepath then return end + if not File.exist? @download_path then FileUtils.mkdir_p "#{@download_path}" end + + filename = File.basename(filepath) + cachefile = File.join(@download_path, filename) + + @log.info "Moving \"#{filename}\" to download cache directory" + @log.info " [path: #{@download_path}]" + + if not File.exist? cachefile then + #FileUtils.ln(filepath, @download_path, :force => true) + if not FileUtil.safeLink(filepath, @download_path) then + @log.info "Failed to link file [#{filepath}] to " + @log.info " [#{@download_path}]" + end + end + + if not File.exist? cachefile then + @log.info "Failed to move [#{filename}] to " + @log.info " [#{@download_path}]" + end + + begin + lock = Utils.file_lock(File.join(CONFIG_PATH,".cache_lock")) + + remove_old_files_in_cache + ensure + Utils.file_unlock(lock) if not lock.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 + if Utils.validatePkgFile(cached_filepath, pkg_checksum, pkg_size) then + FileUtils.touch cached_filepath + return cached_filepath + else + return nil + 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 + + private + def upload_request(ip, port, dock, transporter, binary_path_list) + binary_path_list.each do |bpath| + client2 = BuildCommClient.create(ip, port, @log) + begin + if client2.nil? then + raise RuntimeError, "Failed to create BuildCommClient instance.." + end + + @log.info "Send UPLOAD REQ.. [UPLOAD|#{dock}]" + result = client2.send("UPLOAD|#{dock}") + if not result then + raise RuntimeError, "Failed to send ready REQ.." + end + result = client2.send_file(bpath, transporter) + ensure + client2.terminate + end + end + end + + public + # upload package + def upload(ip, port, binary_path_list, ftp_addr=nil, ftp_port=nil, ftp_username=nil, ftp_passwd=nil, password="") + + # 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 + + 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 + rescue => e + @log.error "FTP failed to put file (exception)" + @log.error "#{e.message}" + @log.error e.backtrace.inspect + return nil + end + + binary_list = [] + binary_path_list.each do |binary_path| + if File.exist? binary_path then + binary_list.push(File.basename(binary_path)) + else + @log.error "Binary file does not exist" + return nil + end + end + + client = BuildCommClient.create(ip, port, @log) + if client.nil? then + @log.error "Can't access server #{ip}:#{port}" + return nil + end + + begin + # create unique dock number + dock = Utils.create_uniq_name() + + dist = get_distribution + if dist.empty? then + @log.error "Distribution is empty.." + return nil + end + + @log.info "Send register message.. [REGISTER|#{dist}|#{password}|DOCK|#{dock}|#{binary_list.join("|")}]" + snapshot = nil + + client.send "REGISTER|#{dist}|#{password}|DOCK|#{dock}|#{binary_list.join("|")}" + + client.read_lines do |line| + if line.eql?("WAITFORUPLOAD") then + # upload + @log.info "Get WAITFORUPLOAD message" + thread = Thread.new do + begin + upload_request(ip, port, dock, transporter, binary_path_list) + rescue => e + puts "Transfering file failed!" + puts e.message + end + end + + thread.join + client.send("REGISTERCONTINUE") + elsif line.start_with? "SUCC" then + snapshot = line.split("|")[1] + elsif line.start_with? "ERROR" then + @log.error line.strip + return nil + else + @log.error "Unknown message received : #{l}" + end + end + ensure + client.terminate + end + + if not snapshot.nil? and not snapshot.empty? then + snapshot = @server_addr + "/snapshots/" + snapshot + @log.info "Registered successfully! [#{binary_path_list.join("|")}]" + if snapshot.empty? then + @log.error "Failed to generate snapshot" + end + + return snapshot + else + return nil + end + 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 + + @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) + + 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) + + pkg_name = Utils.get_package_name_from_package_file( pkg_path ) + pkg_os = Utils.get_os_from_package_file( pkg_path ) + + 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 "\"#{filename}\" 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 + pkg_conflicts = pkg.conflicts + 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 + + # TODO: Resolve conflicts + if not resolve_conflicts_internal(pkg_conflicts) then + @log.error "Failed to resolve conflicts [#{pkg_name}]" + return 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}." + 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 + # get default path for installing + def get_default_inst_dir() + return Dir.pwd + 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] + 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) + end + end + end + + return result + end + + public + # get reverse source dependent packages (just 1 depth) + 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 + # 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 + # 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 install dependent packages for except (considered install priority, reverse, and force) + # reverse : return reverse result + # force : install package force + def get_install_dependent_packages_with_except(pkg_name, os, reverse, force, input_list) + 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_with_except(pkg_name, os, force, 0, input_list) + # 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 + when "conflicts" then return pkg.conflicts + + 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_install_dependency_arr_with_except(pkg_name, os, force, n, input_list) + + 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 !(pkg.install_dep_list.empty?) then + rem_list = [] + pkg.install_dep_list.each do |i| + input_list.each do |j| + if i.package_name.eql? j then + rem_list.push(i) + end + end + end + pkg.install_dep_list = pkg.install_dep_list - rem_list + end + + pkg.install_dep_list.each do |l| + @all_dep_list.push([n, l]) + get_install_dependency_arr_with_except(l.package_name, os, force, n+1, input_list) + 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 + def resolve_conflicts_internal(conflicts_pkgs) + if conflicts_pkgs.nil? then return true end + conflicts_pkgs.each do |pkg| + if check_installed_pkg(pkg.package_name) then + if not uninstall(pkg.package_name, true) then + @log.error "Failed to uninstall [#{pkg.package_name}] package for resolving" + return false + else + @log.info "Resolved conflict package [#{pkg.package_name}]" + end + end + end + return true + end + + private + def resolve_conflicts(pkg_name, os) + conflicts = get_attr_from_pkg(pkg_name, os, "conflicts") + return resolve_conflicts_internal(conflicts) + 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") + + # 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 + + # resolve conflict packages + if not resolve_conflicts(pkg_name, os) then + @log.error "Failed to resolve conflicts [#{pkg_name}]" + return false + end + + # install package + #download + tmp_location = nil + begin + tmp_location = File.join(@tmp_path,Utils.create_uniq_name) + filepath = download(pkg_name, os, false, tmp_location) + if filepath.nil? or filepath[0].nil? then + return false + end + + #install + ret = FileInstaller.install(pkg_name, filepath[0], type, @location, @log) + ensure + #remove garbage + FileUtils.rm_rf tmp_location if not tmp_location.nil? and File.exist? tmp_location + 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.error "Server does not have \"#{ssinfo_file}\" file." + return nil + end + else + if File.exist? file_url then + FileUtils.cp(file_url, @config_dist_path) + else + @log.error "Server does not have \"#{ssinfo_file}\" file." + return nil + 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? "ROOT" then return true + else return false end + end + + public + def register(address, distribution, pkg_file_path, password) + # check file exist + if not File.exist? pkg_file_path then + puts "The file does not exist!.. #{pkg_file_path}" + return false + end + + result = Utils.parse_server_addr(address) + if result.nil? then + puts "Server address is incorrect. (#{address})" + puts "Tune as following format." + puts " :" + exit 1 + end + bs_ip = result[0] + bs_port = result[1] + + pkg_file_path_list = [] + pkg_file_path_list.push(pkg_file_path) + # set distribution + @server_addr = distribution + ret = upload(bs_ip, bs_port, pkg_file_path_list, nil, nil, nil, nil, password) + + if ret then @log.info "Snapshot is generated : #{ret}" end + end + + ##Print change log to console. + public + def printChangeLog(snapshot1 = nil, snapshot2 = nil) + snapshotPath = File.join(@config_dist_path, PackageServerConstants::SNAPSHOT_INFO_FILE_NAME) + @log.info("Read information of snapshot from " + snapshotPath); + + ssController = SnapshotController.new(snapshotPath); + changeLogController = ChangeLogController.new(@server_addr, ssController) + + if (snapshot1.nil?()) then + changeLog = changeLogController.getLatestChangeLog(); + elsif snapshot2.nil?() then + changeLog = changeLogController.getChangeLog(snapshot1); + else + changeLog = changeLogController.getTotalChangeLog(snapshot1, snapshot2); + end + + puts changeLog + end + + ##Print snapshot list to console. + public + def printSnapshotList(showAll=false) + snapshotPath = File.join(@config_dist_path, PackageServerConstants::SNAPSHOT_INFO_FILE_NAME) + @log.info("Read information of snapshot from " + snapshotPath); + + ssController = SnapshotController.new(snapshotPath); + if showAll then + result = ssController.getAllSnapshotList; + else + result = ssController.getManualSnapshotList ; + end + + result.each() do |snapshot| + puts PackageServerConstants::SNAPSHOT_NAME_FIELD + ": " + snapshot.getName() + puts PackageServerConstants::SNAPSHOT_TIME_FIELD + ": " + snapshot.getTime() + puts + end + + end end diff --git a/src/pkg_server/clientOptParser.rb b/src/pkg_server/clientOptParser.rb index 3b2ccfe..1b46b0b 100644 --- a/src/pkg_server/clientOptParser.rb +++ b/src/pkg_server/clientOptParser.rb @@ -31,248 +31,255 @@ $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))+"/common" require "utils" def set_default( options ) - if options[:t].nil? then options[:t] = false end - if options[:type].nil? then options[:type] = 'all' end - if options[:f].nil? then options[:f] = false end - if options[:v].nil? then options[:v] = false end - if options[:all].nil? then options[:all] = false end + if options[:t].nil? then options[:t] = false end + if options[:type].nil? then options[:type] = 'all' end + if options[:f].nil? then options[:f] = false end + if options[:v].nil? then options[:v] = false end + if options[:all].nil? then options[:all] = false end + options[:el] = [] end def option_error_check( options ) - case options[:cmd] - - when "clean" then - - when "upgrade" then - if options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli upgrade -u [-l ] [-o ] [--trace]" - end - - when "check-upgrade" then - if options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli check-upgrade -u [-l ] [-o ]" - end - - when "download" then - if options[:pkg].nil? or options[:pkg].empty? or - options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli download -P -u [-o ] [-l ] [--trace]" - end - when "make-img" then - if options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli make-img -u [-o ] [-m ]" - end - when "dep-graph" then - if options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli dep-graph -u [-o ] [--dep_type ]" - end - when "install" then - if options[:pkg].nil? or options[:pkg].empty? or - options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli install -P -u [-o ] [-l ] [--trace] [--force]" - end - - when "install-file" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli install-file -P [-l ] [-u ] [--trace] [--force]" - end - - when "uninstall" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli uninstall -P [-l ] [--trace]" - end - - when "show-rpkg" then - if options[:pkg].nil? or options[:pkg].empty? or - options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli show-rpkg -P -u [-o ]" - end - - when "list-rpkg" then - if options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli list-rpkg -u [-o ]" - end - - when "show-lpkg" then - if options[:pkg].nil? or options[:pkg].empty? then - raise ArgumentError, "Usage: pkg-cli show-lpkg -P [-l ]" - end - - when "list-lpkg" then - - when "build-dep" then - if options[:pkg].nil? or options[:pkg].empty? or - options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli build-dep -P -u [-o ]" - end - - when "install-dep" then - if options[:pkg].nil? or options[:pkg].empty? or - options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli install-dep -P -u [-o ]" - end - - when "register" - if options[:pkg].nil? or options[:pkg].empty? or options[:address].nil? or options[:address].empty? or - options[:dist].nil? or options[:dist].empty? then - raise ArgumentError, "Usage: pkg-cli register -P -a -d -w " - end - when "snapshotlist" - if options[:url].nil? or options[:url].empty? then - raise ArgumentError, "Usage: pkg-cli install-dep -P -u [-o ]" - end - when "changelog" - - else - raise ArgumentError, "Input is incorrect : #{options[:cmd]}" - end + case options[:cmd] + + when "clean" then + + when "upgrade" then + if options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli upgrade -u [-l ] [-o ] [--trace]" + end + + when "check-upgrade" then + if options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli check-upgrade -u [-l ] [-o ]" + end + + when "download" then + if options[:pkg].nil? or options[:pkg].empty? or + options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli download -P -u [-o ] [-l ] [--trace]" + end + when "make-img" then + if options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli make-img -u [-o ] [-i ]" + end + when "dep-graph" then + if options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli dep-graph -u [-o ] [--dep_type ]" + end + when "install" then + if options[:pkg].nil? or options[:pkg].empty? or + options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli install -P -u [-o ] [-l ] [--trace] [--force]" + end + + when "install-file" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli install-file -P [-l ] [-u ] [--trace] [--force]" + end + + when "uninstall" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli uninstall -P [-l ] [--trace]" + end + + when "show-rpkg" then + if options[:pkg].nil? or options[:pkg].empty? or + options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli show-rpkg -P -u [-o ]" + end + + when "list-rpkg" then + if options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli list-rpkg -u [-o ]" + end + + when "show-lpkg" then + if options[:pkg].nil? or options[:pkg].empty? then + raise ArgumentError, "Usage: pkg-cli show-lpkg -P [-l ]" + end + + when "list-lpkg" then + + when "build-dep" then + if options[:pkg].nil? or options[:pkg].empty? or + options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli build-dep -P -u [-o ]" + end + + when "install-dep" then + if options[:pkg].nil? or options[:pkg].empty? or + options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli install-dep -P -u [-o ]" + end + + when "register" + if options[:pkg].nil? or options[:pkg].empty? or options[:address].nil? or options[:address].empty? or + options[:dist].nil? or options[:dist].empty? then + raise ArgumentError, "Usage: pkg-cli register -P -a -d -w " + end + when "snapshotlist" + if options[:url].nil? or options[:url].empty? then + raise ArgumentError, "Usage: pkg-cli install-dep -P -u [-o ]" + end + when "changelog" + + else + raise ArgumentError, "Input is incorrect : #{options[:cmd]}" + end end def option_parse - options = {} - banner = "Requiest service to package-server and control packages service command-line tool." + "\n" \ - + "\n" + "Usage: pkg-cli [OPTS] or pkg-cli (-h|-v)" + "\n" \ - + "\n" + "Subcommands:" + "\n" \ - + "\t" + "clean Delete the package in your SDK environment." + "\n" \ - + "\t" + "download Download the package in your SDK environment." + "\n" \ - + "\t" + "make-img Make SDK-Image." + "\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" + "snapshotlist Show the snapshot list in your SDK environment." + "\n" \ - + "\t" + "changelog Show the change log 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 clean [-l ] [--force]" + "\n" \ - + "\t" + "pkg-cli download -P -u [-o ] [-l ] [--trace]" + "\n" \ - + "\t" + "pkg-cli make-img -u [-o ] [-i ]" + "\n" \ - + "\t" + "pkg-cli dep-graph -u [-o ] [--dep_type ]" + "\n" \ - + "\t" + "pkg-cli install -P -u [-o ] [-l ] [--trace] [--force]" + "\n" \ - + "\t" + "pkg-cli install-file -P [-l ] [-u ] [--trace] [--force]" + "\n" \ - + "\t" + "pkg-cli uninstall -P [-l ] [--trace]" + "\n" \ - + "\t" + "pkg-cli upgrade -u [-l ] [-o ] [--trace]" + "\n" \ - + "\t" + "pkg-cli check-upgrade -u [-l ] [-o ]" + "\n" \ - + "\t" + "pkg-cli show-rpkg -P -u [-o ]" + "\n" \ - + "\t" + "pkg-cli list-rpkg -u [-o ]" + "\n" \ - + "\t" + "pkg-cli show-lpkg -P [-l ]" + "\n" \ - + "\t" + "pkg-cli list-lpkg [-l ]" + "\n" \ - + "\t" + "pkg-cli snapshotlist -u [--all]" + "\n" \ - + "\t" + "pkg-cli changelog -u [-snapshot ]" + "\n" \ - + "\t" + "pkg-cli build-dep -P -u [-o ]" + "\n" \ - + "\t" + "pkg-cli install-dep -P -u [-o ]" + "\n" \ - + "\t" + "pkg-cli register -P -a -d -w " + "\n" \ - + "\n" + "Options:" + "\n" - - optparse = OptionParser.new(nil, 32, ' '*8) do|opts| - # Set a banner, displayed at the top - # of the help screen. - - - opts.banner = banner - - opts.on( '-P', '--pkg ', 'package name or package file name' ) do |name| - options[:pkg] = name - end - - opts.on( '-o', '--os ', 'target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64' ) do |os| - options[:os] = os - end - - opts.on( '-d', '--dist ', 'distribution name' ) do |dist| - options[:dist] = dist - end - - opts.on( '-u', '--url ', 'package server url: http://127.0.0.1/dibs/unstable' ) do |url| - options[:url] = url - end - - opts.on( '-l', '--loc ', 'install/download location' ) do |loc| - options[:loc] = loc - end - - opts.on( '-w', '--passwd ', 'password' ) do |passwd| - options[:passwd] = passwd - end - - opts.on( '-a', '--address ', 'package server address : 127.0.0.1:2224' ) do |address| - options[:address] = address - 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( '--dep_type ', 'all/build/install' ) do |type| - options[:type] = type - end + options = {} + banner = "Requiest service to package-server and control packages service command-line tool." + "\n" \ + + "\n" + "Usage: pkg-cli [OPTS] or pkg-cli (-h|-v)" + "\n" \ + + "\n" + "Subcommands:" + "\n" \ + + "\t" + "clean Delete the package in your SDK environment." + "\n" \ + + "\t" + "download Download the package in your SDK environment." + "\n" \ + + "\t" + "make-img Make SDK-Image." + "\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" + "snapshotlist Show the snapshot list in your SDK environment." + "\n" \ + + "\t" + "changelog Show the change log 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 clean [-l ] [--force]" + "\n" \ + + "\t" + "pkg-cli download -P -u [-o ] [-l ] [--trace]" + "\n" \ + + "\t" + "pkg-cli make-img -u [-o ] [-i ] [-x ]" + "\n" \ + + "\t" + "pkg-cli dep-graph -u [-o ] [--dep_type ]" + "\n" \ + + "\t" + "pkg-cli install -P -u [-o ] [-l ] [--trace] [--force]" + "\n" \ + + "\t" + "pkg-cli install-file -P [-l ] [-u ] [--trace] [--force]" + "\n" \ + + "\t" + "pkg-cli uninstall -P [-l ] [--trace]" + "\n" \ + + "\t" + "pkg-cli upgrade -u [-l ] [-o ] [--trace]" + "\n" \ + + "\t" + "pkg-cli check-upgrade -u [-l ] [-o ]" + "\n" \ + + "\t" + "pkg-cli show-rpkg -P -u [-o ]" + "\n" \ + + "\t" + "pkg-cli list-rpkg -u [-o ]" + "\n" \ + + "\t" + "pkg-cli show-lpkg -P [-l ]" + "\n" \ + + "\t" + "pkg-cli list-lpkg [-l ]" + "\n" \ + + "\t" + "pkg-cli snapshotlist -u [--all]" + "\n" \ + + "\t" + "pkg-cli changelog -u [-snapshot ]" + "\n" \ + + "\t" + "pkg-cli build-dep -P -u [-o ]" + "\n" \ + + "\t" + "pkg-cli install-dep -P -u [-o ]" + "\n" \ + + "\t" + "pkg-cli register -P -a -d -w " + "\n" \ + + "\n" + "Options:" + "\n" + + optparse = OptionParser.new(nil, 32, ' '*8) do|opts| + # Set a banner, displayed at the top + # of the help screen. + + opts.banner = banner + + opts.on( '-P', '--pkg ', 'package name or package file name' ) do |name| + options[:pkg] = name + end + + opts.on( '-o', '--os ', 'target operating system: ubuntu-32/ubuntu-64/windows-32/windows-64/macos-64' ) do |os| + options[:os] = os + end + + opts.on( '-d', '--dist ', 'distribution name' ) do |dist| + options[:dist] = dist + end + + opts.on( '-u', '--url ', 'package server url: http://127.0.0.1/dibs/unstable' ) do |url| + options[:url] = url + end + + opts.on( '-l', '--loc ', 'install/download location' ) do |loc| + options[:loc] = loc + end + + opts.on( '-w', '--passwd ', 'password' ) do |passwd| + options[:passwd] = passwd + end + + opts.on( '-a', '--address ', 'package server address : 127.0.0.1:2224' ) do |address| + options[:address] = address + 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( '--dep_type ', 'all/build/install' ) do |type| + options[:type] = type + end opts.on( '-i', '--info ', 'sdk image information : http://download.tizen.org/sdk/packages/official' ) do |image_info| - options[:info] = image_info - 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 - - opts.on('--all', 'show all information') do - options[:all] = true - end - - opts.on('-s', '--snapshot snapshotName1,snapshotName2', Array, 'snapshot name') do |snapshotName| - puts snapshotName[0], snapshotName[1] - options[:snapshot] = snapshotName - end - - end - - cmd = ARGV[0] - if cmd.eql? "download" or cmd.eql? "make-img" 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? "dep-graph" 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.eql? "register" or - cmd.eql?("changelog") or - cmd.eql?("snapshotlist") or - cmd =~ /(-v)|(--version)/ or - cmd =~ /(help)|(-h)|(--help)/ then - - if cmd.eql? "help" then - V[0] = "-h" - end - options[:cmd] = ARGV[0] - else - raise ArgumentError, "Usage: pkg-cli [OPTS] or pkg-cli -h" - end - - optparse.parse! - - set_default options - - # option error check - option_error_check options - - return options + options[:info] = image_info + end + + opts.on( '-x', '--exception ', 'meta-package list : MOBILE-3.0,IVI-1.0' ) do |mpackage| + if not Utils.multi_argument_test( mpackage, "," ) then + raise ArgumentError, "meta-package variable parsing error : #{mpackage}" + end + options[:el] = mpackage.split(",") + 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 + + opts.on('--all', 'show all information') do + options[:all] = true + end + + opts.on('-s', '--snapshot snapshotName1,snapshotName2', Array, 'snapshot name') do |snapshotName| + puts snapshotName[0], snapshotName[1] + options[:snapshot] = snapshotName + end + + end + + cmd = ARGV[0] + if cmd.eql? "download" or cmd.eql? "make-img" 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? "dep-graph" 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.eql? "register" or + cmd.eql?("changelog") or + cmd.eql?("snapshotlist") or + cmd =~ /(-v)|(--version)/ or + cmd =~ /(help)|(-h)|(--help)/ then + + if cmd.eql? "help" then + V[0] = "-h" + end + options[:cmd] = ARGV[0] + else + raise ArgumentError, "Usage: pkg-cli [OPTS] or pkg-cli -h" + end + + set_default options + + optparse.parse! + + # option error check + option_error_check options + + return options end -- 2.34.1