task_helpers.rb 5.25 KB
Newer Older
1
require 'rainbow/ext/string'
2
require 'gitlab/utils/strong_memoize'
3

4
# rubocop:disable Rails/Output
5 6 7 8 9
module Gitlab
  TaskFailedError = Class.new(StandardError)
  TaskAbortedByUserError = Class.new(StandardError)

  module TaskHelpers
10 11
    include Gitlab::Utils::StrongMemoize

12 13
    extend self

14 15 16 17 18 19 20 21 22 23 24 25 26 27
    # 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
28 29
      os_name = run_command(%w(lsb_release -irs))
      os_name ||=
Douwe Maan's avatar
Douwe Maan committed
30 31 32 33 34 35 36
        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))
37
          "Mac OS X #{os_x_version}"
Douwe Maan's avatar
Douwe Maan committed
38 39
        elsif File.readable?('/etc/os-release')
          File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
40
        end
Douwe Maan's avatar
Douwe Maan committed
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      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)

90
      raise Gitlab::TaskFailedError.new(output) unless status.zero?
91 92 93 94 95 96 97 98 99

      output
    end

    def uid_for(user_name)
      run_command(%W(id -u #{user_name})).chomp.to_i
    end

    def gid_for(group_name)
100 101 102
      Etc.getgrnam(group_name).gid
    rescue ArgumentError # no group
      "group #{group_name} doesn't exist"
103 104
    end

Gabriel Mazetto's avatar
Gabriel Mazetto committed
105 106 107 108
    def gitlab_user
      Gitlab.config.gitlab.user
    end

109
    def gitlab_user?
110 111 112 113
      strong_memoize(:is_gitlab_user) do
        current_user = run_command(%w(whoami)).chomp
        current_user == gitlab_user
      end
Gabriel Mazetto's avatar
Gabriel Mazetto committed
114 115
    end

116
    def warn_user_is_not_gitlab
117
      return if gitlab_user?
118

119
      strong_memoize(:warned_user_not_gitlab) do
120
        current_user = run_command(%w(whoami)).chomp
121 122 123 124 125 126

        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 ""
127 128 129 130
      end
    end

    def all_repos
131 132 133 134 135 136
      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
137 138 139 140 141 142
          end
        end
      end
    end

    def repository_storage_paths_args
143 144 145
      Gitlab::GitalyClient::StorageSettings.allow_disk_access do
        Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path }
      end
146 147 148 149 150 151
    end

    def user_home
      Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
    end

152 153 154 155 156 157 158
    def checkout_or_clone_version(version:, repo:, target_dir:)
      version =
        if version.starts_with?("=")
          version.sub(/\A=/, '') # tag or branch
        else
          "v#{version}" # tag
        end
159

160 161
      clone_repo(repo, target_dir) unless Dir.exist?(target_dir)
      checkout_version(version, target_dir)
162 163 164 165 166 167
    end

    def clone_repo(repo, target_dir)
      run_command!(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{target_dir}])
    end

168
    def checkout_version(version, target_dir)
169 170
      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 --])
171 172 173
    end
  end
end