BigW Consortium Gitlab

task_helpers.rb 5.06 KB
Newer Older
1
require 'rainbow/ext/string'
2
require 'gitlab/utils/strong_memoize'
3 4 5 6 7 8

module Gitlab
  TaskFailedError = Class.new(StandardError)
  TaskAbortedByUserError = Class.new(StandardError)

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

11 12
    extend self

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

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
      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)

89
      raise Gitlab::TaskFailedError.new(output) unless status.zero?
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

      output
    end

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

    def gid_for(group_name)
      begin
        Etc.getgrnam(group_name).gid
      rescue ArgumentError # no group
        "group #{group_name} doesn't exist"
      end
    end

106 107 108 109
    def gitlab_user
      Gitlab.config.gitlab.user
    end

110
    def gitlab_user?
111 112 113 114
      strong_memoize(:is_gitlab_user) do
        current_user = run_command(%w(whoami)).chomp
        current_user == gitlab_user
      end
115 116
    end

117
    def warn_user_is_not_gitlab
118
      return if gitlab_user?
119

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

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

    def all_repos
132
      Gitlab.config.repositories.storages.each_value do |repository_storage|
133
        IO.popen(%W(find #{repository_storage['path']} -mindepth 2 -type d -name *.git)) do |find|
134 135 136 137 138 139 140 141
          find.each_line do |path|
            yield path.chomp
          end
        end
      end
    end

    def repository_storage_paths_args
142
      Gitlab.config.repositories.storages.values.map { |rs| rs['path'] }
143 144 145 146 147 148
    end

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

149 150 151 152 153 154 155
    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
156

157 158
      clone_repo(repo, target_dir) unless Dir.exist?(target_dir)
      checkout_version(version, target_dir)
159 160 161 162 163 164
    end

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

165
    def checkout_version(version, target_dir)
166 167
      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 --])
168 169 170
    end
  end
end