184 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| require 'rainbow/ext/string'
 | |
| require_dependency 'gitlab/utils/strong_memoize'
 | |
| 
 | |
| # rubocop:disable Rails/Output
 | |
| module Gitlab
 | |
|   TaskFailedError = Class.new(StandardError)
 | |
|   TaskAbortedByUserError = Class.new(StandardError)
 | |
| 
 | |
|   module TaskHelpers
 | |
|     include Gitlab::Utils::StrongMemoize
 | |
| 
 | |
|     extend self
 | |
| 
 | |
|     def invoke_and_time_task(task)
 | |
|       start = Time.now
 | |
|       Rake::Task[task].invoke
 | |
|       puts "`#{task}` finished in #{Time.now - start} seconds"
 | |
|     end
 | |
| 
 | |
|     # Ask if the user wants to continue
 | |
|     #
 | |
|     # Returns "yes" the user chose to continue
 | |
|     # Raises Gitlab::TaskAbortedByUserError if the user chose *not* to continue
 | |
|     def ask_to_continue
 | |
|       answer = prompt("Do you want to continue (yes/no)? ".color(:blue), %w{yes no})
 | |
|       raise Gitlab::TaskAbortedByUserError unless answer == "yes"
 | |
|     end
 | |
| 
 | |
|     # Check which OS is running
 | |
|     #
 | |
|     # It will primarily use lsb_relase to determine the OS.
 | |
|     # It has fallbacks to Debian, SuSE, OS X and systems running systemd.
 | |
|     def os_name
 | |
|       os_name = run_command(%w(lsb_release -irs))
 | |
|       os_name ||=
 | |
|         if File.readable?('/etc/system-release')
 | |
|           File.read('/etc/system-release')
 | |
|         elsif File.readable?('/etc/debian_version')
 | |
|           "Debian #{File.read('/etc/debian_version')}"
 | |
|         elsif File.readable?('/etc/SuSE-release')
 | |
|           File.read('/etc/SuSE-release')
 | |
|         elsif os_x_version = run_command(%w(sw_vers -productVersion))
 | |
|           "Mac OS X #{os_x_version}"
 | |
|         elsif File.readable?('/etc/os-release')
 | |
|           File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
 | |
|         end
 | |
| 
 | |
|       os_name.try(:squish)
 | |
|     end
 | |
| 
 | |
|     # Prompt the user to input something
 | |
|     #
 | |
|     # message - the message to display before input
 | |
|     # choices - array of strings of acceptable answers or nil for any answer
 | |
|     #
 | |
|     # Returns the user's answer
 | |
|     def prompt(message, choices = nil)
 | |
|       begin
 | |
|         print(message)
 | |
|         answer = STDIN.gets.chomp
 | |
|       end while choices.present? && !choices.include?(answer)
 | |
|       answer
 | |
|     end
 | |
| 
 | |
|     # Runs the given command and matches the output against the given pattern
 | |
|     #
 | |
|     # Returns nil if nothing matched
 | |
|     # Returns the MatchData if the pattern matched
 | |
|     #
 | |
|     # see also #run_command
 | |
|     # see also String#match
 | |
|     def run_and_match(command, regexp)
 | |
|       run_command(command).try(:match, regexp)
 | |
|     end
 | |
| 
 | |
|     # Runs the given command
 | |
|     #
 | |
|     # Returns '' if the command was not found
 | |
|     # Returns the output of the command otherwise
 | |
|     #
 | |
|     # see also #run_and_match
 | |
|     def run_command(command)
 | |
|       output, _ = Gitlab::Popen.popen(command)
 | |
|       output
 | |
|     rescue Errno::ENOENT
 | |
|       '' # if the command does not exist, return an empty string
 | |
|     end
 | |
| 
 | |
|     # Runs the given command and raises a Gitlab::TaskFailedError exception if
 | |
|     # the command does not exit with 0
 | |
|     #
 | |
|     # Returns the output of the command otherwise
 | |
|     def run_command!(command)
 | |
|       output, status = Gitlab::Popen.popen(command)
 | |
| 
 | |
|       raise Gitlab::TaskFailedError.new(output) unless status.zero?
 | |
| 
 | |
|       output
 | |
|     end
 | |
| 
 | |
|     def uid_for(user_name)
 | |
|       run_command(%W(id -u #{user_name})).chomp.to_i
 | |
|     end
 | |
| 
 | |
|     def gid_for(group_name)
 | |
|       Etc.getgrnam(group_name).gid
 | |
|     rescue ArgumentError # no group
 | |
|       "group #{group_name} doesn't exist"
 | |
|     end
 | |
| 
 | |
|     def gitlab_user
 | |
|       Gitlab.config.gitlab.user
 | |
|     end
 | |
| 
 | |
|     def gitlab_user?
 | |
|       strong_memoize(:is_gitlab_user) do
 | |
|         current_user = run_command(%w(whoami)).chomp
 | |
|         current_user == gitlab_user
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def warn_user_is_not_gitlab
 | |
|       return if gitlab_user?
 | |
| 
 | |
|       strong_memoize(:warned_user_not_gitlab) do
 | |
|         current_user = run_command(%w(whoami)).chomp
 | |
| 
 | |
|         puts " Warning ".color(:black).background(:yellow)
 | |
|         puts "  You are running as user #{current_user.color(:magenta)}, we hope you know what you are doing."
 | |
|         puts "  Things may work\/fail for the wrong reasons."
 | |
|         puts "  For correct results you should run this as user #{gitlab_user.color(:magenta)}."
 | |
|         puts ""
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def all_repos
 | |
|       Gitlab::GitalyClient::StorageSettings.allow_disk_access do
 | |
|         Gitlab.config.repositories.storages.each_value do |repository_storage|
 | |
|           IO.popen(%W(find #{repository_storage.legacy_disk_path} -mindepth 2 -type d -name *.git)) do |find|
 | |
|             find.each_line do |path|
 | |
|               yield path.chomp
 | |
|             end
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def repository_storage_paths_args
 | |
|       Gitlab::GitalyClient::StorageSettings.allow_disk_access do
 | |
|         Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path }
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def user_home
 | |
|       Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
 | |
|     end
 | |
| 
 | |
|     def checkout_or_clone_version(version:, repo:, target_dir:)
 | |
|       clone_repo(repo, target_dir) unless Dir.exist?(target_dir)
 | |
|       checkout_version(get_version(version), target_dir)
 | |
|     end
 | |
| 
 | |
|     # this function implements the same logic we have in omnibus for dealing with components version
 | |
|     def get_version(component_version)
 | |
|       # If not a valid version string following SemVer it is probably a branch name or a SHA
 | |
|       # commit of one of our own component so it doesn't need `v` prepended
 | |
|       return component_version unless /^\d+\.\d+\.\d+(-rc\d+)?$/.match?(component_version)
 | |
| 
 | |
|       "v#{component_version}"
 | |
|     end
 | |
| 
 | |
|     def clone_repo(repo, target_dir)
 | |
|       run_command!(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{target_dir}])
 | |
|     end
 | |
| 
 | |
|     def checkout_version(version, target_dir)
 | |
|       run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --quiet origin #{version}])
 | |
|       run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout -f --quiet FETCH_HEAD --])
 | |
|     end
 | |
|   end
 | |
| end
 |