lib/u3d/commands.rb in u3d-1.1.5 vs lib/u3d/commands.rb in u3d-1.2.0

- old
+ new

@@ -122,45 +122,46 @@ UI.message "Filtering available versions with release level '#{rl}' [letter '#{letter}']" vcomparators.select! { |vc| vc.version.parts[3] == letter } end sorted_keys = vcomparators.sort.map { |v| v.version.to_s } + show_packages = options[:packages] + packages = UnityModule.load_modules(sorted_keys, cache_versions, os: os) if show_packages + sorted_keys.each do |k| v = cache_versions[k] UI.message "Version #{k}: " + v.to_s.cyan.underline - next unless options[:packages] - inif = nil - begin - inif = U3d::INIparser.load_ini(k, cache_versions, os: os) - rescue StandardError => e - UI.error "Could not load packages for this version (#{e})" - else - UI.message 'Packages:' - inif.each_key { |pack| UI.message " - #{pack}" } - end + next unless show_packages + version_packages = packages[k] + UI.message 'Packages:' + version_packages.each { |package| UI.message " - #{package.id.capitalize}" } end end def install(args: [], options: {}) version = specified_or_current_project_version(args[0]) UI.user_error!("You cannot use the --operating_system and the --install options together") if options[:install] && options[:operating_system] os = valid_os_or_current(options[:operating_system]) - packages = packages_with_unity_first(options) - cache_versions = cache_versions(os, offline: !options[:download]) version = interpret_latest(version, cache_versions) unless cache_versions[version] UI.crash! "No version '#{version}' was found in cache. Either it doesn't exist or u3d doesn't know about it yet. Try refreshing with 'u3d available -f'" return end definition = UnityVersionDefinition.new(version, os, cache_versions) unity = check_unity_presence(version: version) - return unless enforce_setup_coherence(packages, options, unity, definition) + packages = options[:packages] || ['Unity'] + begin + packages = enforce_setup_coherence(packages, options, unity, definition) + rescue InstallationSetupError + return + end + verify_package_names(definition, packages) get_administrative_privileges(options) if options[:install] files = Downloader.fetch_modules(definition, packages: packages, download: options[:download]) @@ -330,16 +331,10 @@ .version.to_s UI.message "Version '#{version}' is #{iversion}." iversion end - def packages_with_unity_first(options) - temp = options[:packages] || ['Unity'] - temp.insert(0, 'Unity') if temp.delete('Unity') - temp - end - def check_unity_presence(version: nil) # idea: we could support matching 5.3.6p3 if passed 5.3.6 installed = Installer.create.installed unity = installed.find { |u| u.version == version } if unity.nil? @@ -355,10 +350,11 @@ def enforce_setup_coherence(packages, options, unity, definition) if options[:all] packages.clear packages.concat(definition.available_packages) end + packages = sort_packages(packages, definition) if options[:install] if unity UI.important "Unity #{unity.version} is already installed" # Not needed since Linux custom u3d files contain only one entry wich is Unity # return false if definition.os == :linux @@ -367,30 +363,75 @@ packages.delete('Unity') # FIXME: Move me to the WindowsInstaller options[:installation_path] ||= unity.root_path if definition.os == :win end - packages.select { |pack| unity.package_installed?(pack) }.each do |pack| - packages.delete pack - UI.important "Ignoring #{pack} module, it is already installed" - end - return false if packages.empty? + # FIXME: unity.package_installed? is not reliable + packages = detect_installed_packages(packages, unity) + packages = detect_missing_dependencies(packages, unity, definition) + raise InstallationSetupError if packages.empty? else - unless packages.include?('Unity') + unless packages.map(&:downcase).include?('unity') UI.error 'Please install Unity before any of its packages' - return false + raise InstallationSetupError end end end - true + packages end # rubocop:enable Metrics/BlockNesting + def sort_packages(packages, definition) + packages.sort do |a, b| + package_a = definition[a] + package_b = definition[b] + if package_a.depends_on?(package_b) # b must come first + 1 + elsif package_b.depends_on?(package_a) # a must come first + -1 + else + a <=> b # Resort to alphabetical sorting + end + end + end + + def detect_installed_packages(packages, unity) + result = packages + packages.select { |pack| unity.package_installed?(pack) }.each do |pack| + result.delete pack + UI.important "Ignoring #{pack} module, it is already installed" + end + result + end + + def detect_missing_dependencies(packages, unity, definition) + result = packages + packages.reject { |package| can_install?(package, unity, definition, packages) }.each do |pack| + # See FIXME for package_installed? + # result.delete pack + package = definition[pack] + UI.important "#{package.name} depends on #{package.depends_on}, but it's neither installed nor being installed." + end + result + end + + def can_install?(package_name, unity, definition, installing) + package = definition[package_name] + return true unless package.depends_on + return true if unity.package_installed?(package.depends_on) + installing.map { |other| definition[other] }.any? do |other| + other.id == package.depends_on || other.name == package.depends_on + end + end + def get_administrative_privileges(options) U3dCore::Globals.use_keychain = true if options[:keychain] && Helper.mac? UI.important 'Root privileges are required' raise 'Could not get administrative privileges' unless U3dCore::CommandExecutor.has_admin_privileges? end end end # rubocop:enable ClassLength +end + +class InstallationSetupError < StandardError end