#!/usr/bin/env ruby require 'find' require 'net/http' require 'uri' require 'digest/sha1' require 'json' require 'fileutils' @command = ARGV[0] @pkgName = ARGV[1] CREW_PREFIX = '/usr/local' CREW_LIB_PATH = CREW_PREFIX + '/lib/crew/' CREW_CONFIG_PATH = CREW_PREFIX + '/etc/crew/' CREW_BREW_DIR = CREW_PREFIX + '/tmp/crew/' CREW_DEST_DIR = CREW_BREW_DIR + '/dest' $LOAD_PATH.push CREW_LIB_PATH USER = `whoami`.chomp @device = JSON.parse(File.read(CREW_CONFIG_PATH + 'device.json'), symbolize_names: true) #symbolize also values @device.each do |key, elem| @device[key] = @device[key].to_sym rescue @device[key] end def setPkg (pkgName, silent = false) require CREW_LIB_PATH + 'packages/' + pkgName @pkg = Object.const_get(pkgName.capitalize) @pkg.name = pkgName puts "Found #{pkgName}, version #{@pkg.version}" unless silent end def search (pkgName, silent = false) Find.find (CREW_LIB_PATH + 'packages') do |filename| return setPkg(pkgName, silent) if filename == CREW_LIB_PATH + 'packages/' + pkgName + '.rb' end abort "package #{pkgName} not found :(" end def download if @pkg.binary_url && @pkg.binary_url.has_key?(@device[:architecture]) url = @pkg.binary_url[@device[:architecture]] source = false puts "Precompiled binary available, downloading..." else url = @pkg.source_url source = true puts "No precompiled binary available for your platform, downloading source..." end uri = URI.parse url filename = File.basename(uri.path) if source sha1sum = @pkg.source_sha1 else sha1sum = @pkg.binary_sha1[@device[:architecture]] end Dir.chdir CREW_BREW_DIR do system('wget', '--content-disposition', '--no-check-certificate', '-N', url) abort 'Checksum mismatch :/ try again' unless Digest::SHA1.hexdigest( File.read("./#{filename}") ) == sha1sum end puts "Archive downloaded" return {source: source, filename: filename} end def resolveDependenciesAndInstall origin = @pkgName resolveDependencies search origin install #cleanup unless ARGV[2] == 'keep' Dir.chdir CREW_BREW_DIR do system "rm -rf *" system "mkdir dest" #this is a little ugly, feel free to find a better way end end end def resolveDependencies @dependencies = [] def pushDeps if @pkg.dependencies @dependencies << @pkg.dependencies @pkg.dependencies.each do |dep| search dep, true pushDeps end end end pushDeps return if @dependencies.empty? puts "Following packages also need to be installed: " @dependencies.flatten!.each do |dep| print dep + " " end puts "" puts "Do you agree? [Y/n]" response = STDIN.getc case response when "n" abort "No changes made." when "\n", "y", "Y" puts "Proceeding..." proceed = true else puts "I don't understand '#{response}' :(" abort "No changes made." end if proceed @dependencies.each do |dep| search dep install end end end def install if @device[:installed_packages].any? { |pkg| pkg[:name] == @pkg.name } puts "Package #{@pkg.name} already installed, skipping..." return end unless @pkg.is_fake? meta = download Dir.chdir CREW_BREW_DIR do puts "Unpacking archive, this may take a while..." system "tar", "xf", meta[:filename] if meta[:source] == true abort "You don't have a working C compiler. Run 'crew install buildessential' to get one and try again." unless system("gcc", "--version") topdir = `tar -tf #{meta[:filename]} | sed -e 's@/.*@@' | uniq`.chomp! Dir.chdir CREW_BREW_DIR + topdir do puts "Building from source, this may take a while..." @pkg.build system "rm -rf", CREW_DEST_DIR + "/*" #wipe crew destdir puts "Preconfiguring package..." @pkg.install end Dir.chdir CREW_DEST_DIR do #create directory list system "find . -type f > ../filelist" system "find . -type l >> ../filelist" system "cut -c2- ../filelist > filelist" #create file list system "find . -type d > ../dlist" system "cut -c2- ../dlist > dlistcut" system "tail -n +2 dlistcut > dlist" #remove temporary files system "rm dlistcut ../dlist ../filelist" #create resulting folders list directories = [] Dir.glob('*').select do |fn| if File.directory?(fn) directories.push(fn) end end #wipe directories with the same name in brew dir to avoid conflicts directories.each do |dir| system "rm -rf ../" + dir.chomp end #move result files and directories to brew dir system "mv * ../" end end puts "Installing..." FileUtils.mv 'dlist', CREW_CONFIG_PATH + "meta/#{@pkg.name}.directorylist" FileUtils.mv 'filelist', CREW_CONFIG_PATH + "meta/#{@pkg.name}.filelist" File.open(CREW_CONFIG_PATH + "meta/#{@pkg.name}.directorylist").each_line do |line| system "sudo", "mkdir", "-p", line.chomp end File.open(CREW_CONFIG_PATH + "meta/#{@pkg.name}.filelist").each_line do |line| system "sudo", "mv", CREW_BREW_DIR + line.chomp, line.chomp end end end #add to installed packages @device[:installed_packages].push(name: @pkg.name, version: @pkg.version) File.open(CREW_CONFIG_PATH + 'device.json', 'w') do |file| output = JSON.parse @device.to_json file.write JSON.pretty_generate(output) end puts "#{@pkg.name.capitalize} installed!" end def remove unless @device[:installed_packages].any? { |pkg| pkg[:name] == @pkg.name } puts "Package #{@pkg.name} isn't installed." return end unless @pkg.is_fake? Dir.chdir CREW_CONFIG_PATH do File.open("meta/#{@pkg.name}.filelist").each_line do |line| begin File.unlink line.chomp rescue => exception #swallow exception end end File.readlines("meta/#{@pkg.name}.directorylist").reverse.each do |line| begin Dir.rmdir line.chomp rescue => exception #swallow exception end end File.unlink "meta/#{@pkg.name}.filelist" File.unlink "meta/#{@pkg.name}.directorylist" end end #remove from installed packages @device[:installed_packages].each do |elem| @device[:installed_packages].delete elem if elem[:name] == @pkg.name end File.open(CREW_CONFIG_PATH + 'device.json', 'w') do |file| out = JSON.parse @device.to_json file.write JSON.pretty_generate(out) end puts "#{@pkgName.capitalize} removed!" end case @command when "search" search @pkgName when "download" search @pkgName download when "update" unless @pkgName == 'crew' Dir.chdir CREW_LIB_PATH do system "git fetch origin master" system "git reset --hard origin/master" end puts "Package lists updated." else abort 'Updating crew itself must be done as root.' unless USER == 'root' #update crew binary Dir.chdir CREW_PREFIX + '/bin' do system "wget", "-N", "https://raw.github.com/skycocker/chromebrew/master/crew" system "sudo", "chmod", "+x", "crew" end #update crew library Dir.chdir CREW_LIB_PATH do system "wget", "-N", "https://raw.github.com/skycocker/chromebrew/master/lib/package.rb" system "wget", "-N", "https://raw.github.com/skycocker/chromebrew/master/lib/package_helpers.rb" end end when "install" search @pkgName resolveDependenciesAndInstall when "remove" abort 'Removing actions must be ran with sudo.' unless USER == 'root' search @pkgName remove when nil puts "Chromebrew, version 0.1" puts "Usage: crew [command] [package]" puts "Available commands: search, download, install, remove" else puts "I have no idea how to do #{@command} :(" puts "Available commands: search, download, install, remove" end