2018-10-22 03:00:50 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-11-29 13:21:25 -05:00
|
|
|
require 'rainbow/ext/string'
|
2019-01-21 14:20:38 -05:00
|
|
|
require_dependency 'gitlab/utils/strong_memoize'
|
2016-11-29 13:21:25 -05:00
|
|
|
|
2018-01-24 05:01:45 -05:00
|
|
|
# rubocop:disable Rails/Output
|
2016-11-29 13:21:25 -05:00
|
|
|
module Gitlab
|
|
|
|
TaskFailedError = Class.new(StandardError)
|
|
|
|
TaskAbortedByUserError = Class.new(StandardError)
|
|
|
|
|
|
|
|
module TaskHelpers
|
2017-11-17 07:27:16 -05:00
|
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
|
2017-08-08 11:14:29 -04:00
|
|
|
extend self
|
|
|
|
|
2019-01-21 14:20:38 -05:00
|
|
|
def invoke_and_time_task(task)
|
|
|
|
start = Time.now
|
|
|
|
Rake::Task[task].invoke
|
|
|
|
puts "`#{task}` finished in #{Time.now - start} seconds"
|
|
|
|
end
|
|
|
|
|
2016-11-29 13:21:25 -05:00
|
|
|
# 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
|
2020-09-03 14:08:29 -04:00
|
|
|
return if Gitlab::Utils.to_boolean(ENV['GITLAB_ASSUME_YES'])
|
|
|
|
|
2016-11-29 13:21:25 -05:00
|
|
|
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
|
2017-02-22 13:18:40 -05:00
|
|
|
os_name = run_command(%w(lsb_release -irs))
|
|
|
|
os_name ||=
|
2017-02-23 10:27:36 -05:00
|
|
|
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))
|
2017-02-22 13:18:40 -05:00
|
|
|
"Mac OS X #{os_x_version}"
|
2017-02-23 10:27:36 -05:00
|
|
|
elsif File.readable?('/etc/os-release')
|
|
|
|
File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
|
2017-02-22 13:18:40 -05:00
|
|
|
end
|
2017-02-23 10:27:36 -05:00
|
|
|
|
2018-10-22 03:00:50 -04:00
|
|
|
os_name.try(:squish)
|
2016-11-29 13:21:25 -05:00
|
|
|
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)
|
2021-06-08 11:10:00 -04:00
|
|
|
answer = $stdin.gets.chomp
|
2016-11-29 13:21:25 -05:00
|
|
|
end while choices.present? && !choices.include?(answer)
|
|
|
|
answer
|
|
|
|
end
|
|
|
|
|
2021-02-02 01:09:47 -05:00
|
|
|
# Prompt the user to input a password
|
|
|
|
#
|
|
|
|
# message - custom message to display before input
|
|
|
|
def prompt_for_password(message = 'Enter password: ')
|
2021-06-08 11:10:00 -04:00
|
|
|
unless $stdin.tty?
|
2021-02-02 01:09:47 -05:00
|
|
|
print(message)
|
2021-06-08 11:10:00 -04:00
|
|
|
return $stdin.gets.chomp
|
2021-02-02 01:09:47 -05:00
|
|
|
end
|
|
|
|
|
2021-06-08 11:10:00 -04:00
|
|
|
$stdin.getpass(message)
|
2021-02-02 01:09:47 -05:00
|
|
|
end
|
|
|
|
|
2016-11-29 13:21:25 -05:00
|
|
|
# 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)
|
|
|
|
|
2021-05-04 11:10:36 -04:00
|
|
|
raise Gitlab::TaskFailedError, output unless status == 0
|
2016-11-29 13:21:25 -05:00
|
|
|
|
|
|
|
output
|
|
|
|
end
|
|
|
|
|
|
|
|
def uid_for(user_name)
|
|
|
|
run_command(%W(id -u #{user_name})).chomp.to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
def gid_for(group_name)
|
2018-01-24 05:01:45 -05:00
|
|
|
Etc.getgrnam(group_name).gid
|
|
|
|
rescue ArgumentError # no group
|
|
|
|
"group #{group_name} doesn't exist"
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
|
2017-05-31 05:32:11 -04:00
|
|
|
def gitlab_user
|
|
|
|
Gitlab.config.gitlab.user
|
|
|
|
end
|
|
|
|
|
2017-08-24 12:58:09 -04:00
|
|
|
def gitlab_user?
|
2017-11-17 07:27:16 -05:00
|
|
|
strong_memoize(:is_gitlab_user) do
|
|
|
|
current_user = run_command(%w(whoami)).chomp
|
|
|
|
current_user == gitlab_user
|
|
|
|
end
|
2017-05-31 05:32:11 -04:00
|
|
|
end
|
|
|
|
|
2016-11-29 13:21:25 -05:00
|
|
|
def warn_user_is_not_gitlab
|
2017-11-17 07:27:16 -05:00
|
|
|
return if gitlab_user?
|
2017-05-30 13:06:58 -04:00
|
|
|
|
2017-11-17 07:27:16 -05:00
|
|
|
strong_memoize(:warned_user_not_gitlab) do
|
2017-02-22 13:18:40 -05:00
|
|
|
current_user = run_command(%w(whoami)).chomp
|
2017-05-30 13:06:58 -04:00
|
|
|
|
|
|
|
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 ""
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def all_repos
|
2018-06-05 11:51:14 -04:00
|
|
|
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
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def repository_storage_paths_args
|
2018-06-05 11:58:28 -04:00
|
|
|
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
|
|
|
|
Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path }
|
|
|
|
end
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def user_home
|
|
|
|
Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
|
|
|
|
end
|
|
|
|
|
2020-05-14 11:08:14 -04:00
|
|
|
def checkout_or_clone_version(version:, repo:, target_dir:, clone_opts: [])
|
|
|
|
clone_repo(repo, target_dir, clone_opts: clone_opts) unless Dir.exist?(target_dir)
|
2019-10-28 17:06:24 -04:00
|
|
|
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}"
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
|
2020-05-14 11:08:14 -04:00
|
|
|
def clone_repo(repo, target_dir, clone_opts: [])
|
|
|
|
run_command!(%W[#{Gitlab.config.git.bin_path} clone] + clone_opts + %W[-- #{repo} #{target_dir}])
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
|
2017-04-10 19:15:48 -04:00
|
|
|
def checkout_version(version, target_dir)
|
2021-12-16 13:14:09 -05:00
|
|
|
# Explicitly setting the git protocol version to v2 allows older Git binaries
|
|
|
|
# to do have a shallow clone obtain objects by object ID.
|
|
|
|
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} config protocol.version 2])
|
2017-07-20 17:30:29 -04:00
|
|
|
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 --])
|
2016-11-29 13:21:25 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|