# lib/convenience_functions.rb # Extracted bits of crew-specific code that we use frequently enough that it makes sense to split them out to here. require 'json' require_relative 'color' require_relative 'const' require_relative 'crewlog' require_relative 'downloader' # Reimplementation of .blank? method from ActiveSupport class NilClass; def blank? = true; end class Numeric; def blank? = false; end class Proc; def blank? = false; end class Array; def blank? = empty?; end class Hash; def blank? = empty?; end class Symbol; def blank? = empty?; end class String; def blank? = strip.empty?; end class ConvenienceFunctions def self.determine_conflicts(pkg_name, filelist = File.join(CREW_META_PATH, "#{pkg_name}.filelist"), exclude_suffix = nil, verbose: false) conflicts = {} target_filelist = File.readlines(filelist, chomp: true).grep(/^(?!#)/) puts 'Checking for conflicts with files from installed packages...'.orange if verbose Dir[File.join(CREW_META_PATH, '*.filelist')].each do |filelist| filelist_name = File.basename(filelist, '.filelist') # skip filelist belongs to the same package/explicitly excluded next if pkg_name == filelist_name || (exclude_suffix && filelist_name.end_with?(exclude_suffix)) # find out identical file paths with intersection conflict = (target_filelist & File.readlines(filelist, chomp: true)).reject(&:empty?) conflicts[filelist_name] = conflict if conflict.any? end return conflicts end def self.get_package_disk_size(filelist) filelist.sum do |filename| # Skip calculating the filesize if the file doesn't exist. next 0 unless File.file?(filename) # Ignore symlinks to prevent duplicating calculation. next 0 if File.symlink?(filename) # Add the size of the file to the total size. File.size(filename) end end def self.load_symbolized_json unless File.file?(File.join(CREW_CONFIG_PATH, 'device.json')) puts 'Creating device.json.' device = { 'architecture' => ARCH, 'installed_packages' => [] } FileUtils.mkdir_p CREW_CONFIG_PATH File.write(File.join(CREW_CONFIG_PATH, 'device.json'), JSON[device]) end return JSON.load_file(File.join(CREW_CONFIG_PATH, 'device.json'), symbolize_names: true).transform_values! { |val| val.is_a?(String) ? val.to_sym : val } end def self.read_filelist(path, always_calcuate_from_disk: false) filelist = File.readlines(path, chomp: true) if filelist.first&.start_with?('# Total size') && !always_calcuate_from_disk return [filelist.first[/Total size: (\d+)/, 1].to_i, filelist] else return [get_package_disk_size(filelist), filelist] end end def self.save_json(json_object) crewlog 'Saving device.json...' begin File.write File.join(CREW_CONFIG_PATH, 'device.json.tmp'), JSON.pretty_generate(JSON.parse(json_object.to_json)) rescue StandardError => e puts "Error writing updated packages json file!\n#{e.message}".lightred abort end # Copy over original if the write to the tmp file succeeds. FileUtils.cp("#{CREW_CONFIG_PATH}/device.json.tmp", File.join(CREW_CONFIG_PATH, 'device.json')) && FileUtils.rm("#{CREW_CONFIG_PATH}/device.json.tmp") end def self.libtoolize(library, lib_pkg_name = nil, install_dest = nil) install_dest = false if install_dest.nil? lib_pkg_name = library if lib_pkg_name.nil? libname = library.to_s.start_with?('lib') ? library.downcase : "lib#{library.downcase}" puts "Generating libtool file for #{lib_pkg_name}".orange puts "grep \"#{CREW_LIB_PREFIX}/#{libname}.so\\\|#{CREW_DEST_LIB_PREFIX}/#{libname}-*.so\" #{CREW_META_PATH}/#{lib_pkg_name}.filelist" if CREW_VERBOSE libnames = `grep "#{CREW_LIB_PREFIX}/#{libname}.so\\\|#{CREW_DEST_LIB_PREFIX}/#{libname}-*.so*" #{CREW_META_PATH}/#{lib_pkg_name}.filelist`.chomp.split(/$/).map(&:strip) libnames.each do |s| s.gsub!("#{CREW_LIB_PREFIX}/", '') end return if libnames.empty? dlname = libnames.grep(/.so(.)?/).first libname = dlname.gsub(/.so(.\d+)?/, '') longest_libname = libnames.max_by(&:length) libvars = longest_libname.rpartition('.so.')[2].split('.') libtool_file = <<~LIBTOOLEOF # #{libname}.la - a libtool library file # Generated by libtool (GNU libtool) (Created by Chromebrew) # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='#{dlname}' # Names of this library. library_names='#{libnames.reverse.join(' ')}' # The name of the static archive. old_library='#{libname}.a' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='' # Libraries that this one depends upon. dependency_libs='' # Names of additional weak libraries provided by this library weak_library_names='' # Version information for #{library}. current=#{libvars[1]} age=#{libvars[1]} revision=#{libvars[2]} # Is this an already installed library? installed=yes # Should we warn about portability when linking against -modules? shouldnotlink=no # Files to dlopen/dlpreopen dlopen='' dlpreopen='' # Directory that this library needs to be installed in: libdir='#{CREW_LIB_PREFIX}' LIBTOOLEOF File.write("#{libname}.la", libtool_file) %W[#{CREW_LIB_PREFIX}/#{libname}.la #{"#{CREW_DEST_LIB_PREFIX}/#{libname}.la" if install_dest}].reject(&:blank?).each do |lib| FileUtils.install "#{libname}.la", lib, mode: 0o755 puts "Generated #{lib}..." end end def self.patch(patch_array = []) return if patch_array.empty? patch_array.each do |patch_item| abort 'Patch array is not valid!'.lightred unless patch_item[0] abort 'Patch sha256sum does not exist!'.lightred unless patch_item[1] patch_file = File.basename(patch_item[0]) puts "downloader #{patch_item[0]}, #{patch_item[1]}" if CREW_VERBOSE downloader patch_item[0], patch_item[1] puts "patch -Np1 -i #{patch_file}" if CREW_VERBOSE system "patch -Np1 -i #{patch_file}" end end def self.set_default_browser(browser_name, browser_binary) print "\nSet #{browser_name} as your default browser? [Y/n]: " case $stdin.gets.chomp.downcase when '', 'y', 'yes' Dir.chdir("#{CREW_PREFIX}/bin") do FileUtils.ln_sf browser_binary, 'x-www-browser' end puts "#{browser_name} is now your default browser.".lightgreen else puts 'No change has been made.'.orange end ExitMessage.add "\nType '#{browser_binary}' to get started.\n" end def self.unset_default_browser(browser_name, browser_binary) Dir.chdir("#{CREW_PREFIX}/bin") do if File.exist?('x-www-browser') && File.symlink?('x-www-browser') && ["#{CREW_PREFIX}/share/#{browser_name.downcase}/#{browser_binary}", "#{CREW_PREFIX}/bin/#{browser_binary}"].include?(File.realpath('x-www-browser')) FileUtils.rm "#{CREW_PREFIX}/bin/x-www-browser" end end end end