diff options
Diffstat (limited to 'ruby/lib')
-rw-r--r-- | ruby/lib/gitlab/git/branch.rb | 11 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/commit.rb | 250 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/hook.rb | 141 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/popen.rb | 51 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/push_options.rb | 27 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/ref.rb | 53 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/repository.rb | 282 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/tag.rb | 49 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/user.rb | 36 |
9 files changed, 0 insertions, 900 deletions
diff --git a/ruby/lib/gitlab/git/branch.rb b/ruby/lib/gitlab/git/branch.rb deleted file mode 100644 index 9618b5fef..000000000 --- a/ruby/lib/gitlab/git/branch.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative 'ref' - -module Gitlab - module Git - class Branch < Ref - def initialize(repository, name, target, target_commit) - super(repository, name, target, target_commit) - end - end - end -end diff --git a/ruby/lib/gitlab/git/commit.rb b/ruby/lib/gitlab/git/commit.rb deleted file mode 100644 index 5235b1c46..000000000 --- a/ruby/lib/gitlab/git/commit.rb +++ /dev/null @@ -1,250 +0,0 @@ -module Gitlab - module Git - class Commit - include Gitlab::EncodingHelper - - attr_accessor :raw_commit, :head - - MAX_COMMIT_MESSAGE_DISPLAY_SIZE = 10.megabytes - MIN_SHA_LENGTH = 7 - SERIALIZE_KEYS = %i[ - id message parent_ids - authored_date author_name author_email - committed_date committer_name committer_email trailers - ].freeze - - attr_accessor *SERIALIZE_KEYS # rubocop:disable Lint/AmbiguousOperator - - def ==(other) - return false unless other.is_a?(Gitlab::Git::Commit) - - id && id == other.id - end - - class << self - # Get single commit - # - # Ex. - # Commit.find(repo, '29eda46b') - # - # Commit.find(repo, 'master') - # - def find(repo, commit_id = "HEAD") - # Already a commit? - return commit_id if commit_id.is_a?(Gitlab::Git::Commit) - - # A rugged reference? - commit_id = Gitlab::Git::Ref.dereference_object(commit_id) - return decorate(repo, commit_id) if commit_id.is_a?(Rugged::Commit) - - # Some weird thing? - return nil unless commit_id.is_a?(String) - - # This saves us an RPC round trip. - return nil if commit_id.include?(':') - - commit = rugged_find(repo, commit_id) - - decorate(repo, commit) if commit - rescue Rugged::ReferenceError, Rugged::InvalidError, Rugged::ObjectError, - Gitlab::Git::CommandError, Gitlab::Git::Repository::NoRepository, - Rugged::OdbError, Rugged::TreeError, ArgumentError - nil - end - - def rugged_find(repo, commit_id) - obj = repo.rev_parse_target(commit_id) - - obj.is_a?(Rugged::Commit) ? obj : nil - end - - def decorate(repository, commit, ref = nil) - Gitlab::Git::Commit.new(repository, commit, ref) - end - - def shas_with_signatures(repository, shas) - shas.select do |sha| - begin - Rugged::Commit.extract_signature(repository.rugged, sha) - rescue Rugged::OdbError - false - end - end - end - end - - def initialize(repository, raw_commit, head = nil) - raise "Nil as raw commit passed" unless raw_commit - - @repository = repository - @head = head - - case raw_commit - when Hash - init_from_hash(raw_commit) - when Rugged::Commit - init_from_rugged(raw_commit) - when Gitaly::GitCommit - init_from_gitaly(raw_commit) - else - raise "Invalid raw commit type: #{raw_commit.class}" - end - end - - def sha - id - end - - def short_id(length = 10) - id.to_s[0..length] - end - - def safe_message - @safe_message ||= message - end - - def no_commit_message - "--no commit message" - end - - def to_hash - serialize_keys.map.with_object({}) do |key, hash| - hash[key] = send(key) - end - end - - def date - committed_date - end - - def parents - parent_ids.map { |oid| self.class.find(@repository, oid) }.compact - end - - def message - encode! @message - end - - def author_name - encode! @author_name - end - - def author_email - encode! @author_email - end - - def committer_name - encode! @committer_name - end - - def committer_email - encode! @committer_email - end - - def rugged_commit - @rugged_commit ||= if raw_commit.is_a?(Rugged::Commit) - raw_commit - else - @repository.rev_parse_target(id) - end - end - - def merge_commit? - parent_ids.size > 1 - end - - def to_gitaly_commit - return raw_commit if raw_commit.is_a?(Gitaly::GitCommit) - - message_split = raw_commit.message.split("\n", 2) - Gitaly::GitCommit.new( - id: raw_commit.oid, - subject: message_split[0] ? message_split[0].chomp.b : "", - body: raw_commit.message.b, - parent_ids: raw_commit.parent_ids, - author: gitaly_commit_author_from_rugged(raw_commit.author), - committer: gitaly_commit_author_from_rugged(raw_commit.committer), - trailers: gitaly_trailers_from_rugged(raw_commit) - ) - end - - private - - def init_from_hash(hash) - raw_commit = hash.symbolize_keys - - serialize_keys.each do |key| - send("#{key}=", raw_commit[key]) - end - end - - def init_from_rugged(commit) - author = commit.author - committer = commit.committer - - @raw_commit = commit - @id = commit.oid - @message = commit.message - @authored_date = author[:time] - @committed_date = committer[:time] - @author_name = author[:name] - @author_email = author[:email] - @committer_name = committer[:name] - @committer_email = committer[:email] - @parent_ids = commit.parents.map(&:oid) - @trailers = Hash[commit.trailers] - end - - def init_from_gitaly(commit) - @raw_commit = commit - @id = commit.id - # TODO: Once gitaly "takes over" Rugged consider separating the - # subject from the message to make it clearer when there's one - # available but not the other. - @message = message_from_gitaly_body - @authored_date = init_date_from_gitaly(commit.author) - @author_name = commit.author.name.dup - @author_email = commit.author.email.dup - @committed_date = init_date_from_gitaly(commit.committer) - @committer_name = commit.committer.name.dup - @committer_email = commit.committer.email.dup - @parent_ids = Array(commit.parent_ids) - @trailers = Hash[commit.trailers.map { |t| [t.key, t.value] }] - end - - # Gitaly provides a UNIX timestamp in author.date.seconds, and a timezone - # offset in author.timezone. If the latter isn't present, assume UTC. - def init_date_from_gitaly(author) - if author.timezone.present? - Time.strptime("#{author.date.seconds} #{author.timezone}", '%s %z') - else - Time.at(author.date.seconds).utc - end - end - - def serialize_keys - SERIALIZE_KEYS - end - - def gitaly_commit_author_from_rugged(author_or_committer) - Gitaly::CommitAuthor.new( - name: author_or_committer[:name].b, - email: author_or_committer[:email].b, - date: Google::Protobuf::Timestamp.new(seconds: author_or_committer[:time].to_i) - ) - end - - def gitaly_trailers_from_rugged(rugged_commit) - rugged_commit.trailers.map do |(key, value)| - Gitaly::CommitTrailer.new(key: key, value: value) - end - end - - def message_from_gitaly_body - return @raw_commit.subject.dup if @raw_commit.body_size.zero? - - @raw_commit.body.dup - end - end - end -end diff --git a/ruby/lib/gitlab/git/hook.rb b/ruby/lib/gitlab/git/hook.rb deleted file mode 100644 index 8084cd74c..000000000 --- a/ruby/lib/gitlab/git/hook.rb +++ /dev/null @@ -1,141 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Git - class Hook - def self.directory - Gitlab.config.git.hooks_directory - end - - GL_PROTOCOL = 'web' - attr_reader :name, :path, :repository - - def initialize(name, repository) - @name = name - @repository = repository - @path = File.join(self.class.directory, name) - end - - def repo_path - repository.path - end - - def exists? - File.exist?(path) - end - - def trigger(gl_id, gl_username, oldrev, newrev, ref, push_options: nil, transaction: nil) - return [true, nil] unless exists? - - Bundler.with_unbundled_env do - case name - when "pre-receive", "post-receive" - call_receive_hook(gl_id, gl_username, oldrev, newrev, ref, push_options, transaction) - when "reference-transaction" - call_reference_transaction_hook(gl_id, gl_username, oldrev, newrev, ref, transaction) - when "update" - call_update_hook(gl_id, gl_username, oldrev, newrev, ref, transaction) - end - end - end - - private - - def call_stdin_hook(args, input, env) - exit_status = false - exit_message = nil - - options = { - chdir: repo_path - } - - Open3.popen3(env, path, *args, options) do |stdin, stdout, stderr, wait_thr| - exit_status = true - stdin.sync = true - - # in git, hooks may just exit without reading stdin. We catch the - # exception to avoid a broken pipe warning - begin - input.lines do |line| - stdin.puts line - end - rescue Errno::EPIPE - end - - stdin.close - - unless wait_thr.value == 0 - exit_status = false - exit_message = retrieve_error_message(stderr, stdout) - end - end - - [exit_status, exit_message] - end - - def call_receive_hook(gl_id, gl_username, oldrev, newrev, ref, push_options, transaction) - changes = [oldrev, newrev, ref].join(" ") - - vars = env_base_vars(gl_id, gl_username, transaction) - vars.merge!(push_options.env_data) if push_options - - call_stdin_hook([], changes, vars) - end - - def call_reference_transaction_hook(gl_id, gl_username, oldrev, newrev, ref, transaction) - changes = [oldrev, newrev, ref].join(" ") - - vars = env_base_vars(gl_id, gl_username, transaction) - - call_stdin_hook(["prepared"], changes, vars) - end - - def call_update_hook(gl_id, gl_username, oldrev, newrev, ref, transaction) - options = { - chdir: repo_path - } - - args = [ref, oldrev, newrev] - - vars = env_base_vars(gl_id, gl_username, transaction) - - stdout, stderr, status = Open3.capture3(vars, path, *args, options) - [status.success?, stderr.presence || stdout] - end - - def retrieve_error_message(stderr, stdout) - err_message = stderr.read - err_message = err_message.blank? ? stdout.read : err_message - err_message - end - - def hooks_payload(gl_id, gl_username, transaction) - payload = { - repository: repository.gitaly_repository.to_json, - binary_directory: Gitlab.config.gitaly.bin_dir, - git_path: Gitlab.config.git.bin_path, - internal_socket: Gitlab.config.gitaly.internal_socket, - internal_socket_token: ENV['GITALY_TOKEN'], - user_details: { - userid: gl_id, - username: gl_username, - protocol: GL_PROTOCOL - } - } - - payload.merge!(transaction.payload) if transaction - - Base64.strict_encode64(payload.to_json) - end - - def env_base_vars(gl_id, gl_username, transaction = nil) - { - 'GITALY_HOOKS_PAYLOAD' => hooks_payload(gl_id, gl_username, transaction), - 'GITALY_LOG_DIR' => Gitlab.config.logging.dir, - 'PWD' => repo_path, - 'GIT_DIR' => repo_path - } - end - end - end -end diff --git a/ruby/lib/gitlab/git/popen.rb b/ruby/lib/gitlab/git/popen.rb deleted file mode 100644 index 5d8218eb1..000000000 --- a/ruby/lib/gitlab/git/popen.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'open3' - -module Gitlab - module Git - module Popen - FAST_GIT_PROCESS_TIMEOUT = 15.seconds - - def popen(cmd, path, vars = {}, include_stderr: true, lazy_block: nil) - raise "System commands must be given as an array of strings" unless cmd.is_a?(Array) - - path ||= Dir.pwd - vars['PWD'] = path - options = { chdir: path } - - cmd_output = "" - cmd_status = 0 - Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| - stdout.set_encoding(Encoding::ASCII_8BIT) - stderr.set_encoding(Encoding::ASCII_8BIT) - - # stderr and stdout pipes can block if stderr/stdout aren't drained: https://bugs.ruby-lang.org/issues/9082 - # Mimic what Ruby does with capture3: https://github.com/ruby/ruby/blob/1ec544695fa02d714180ef9c34e755027b6a2103/lib/open3.rb#L257-L273 - err_reader = Thread.new { stderr.read } - - begin - yield(stdin) if block_given? - stdin.close - - if lazy_block - cmd_output = lazy_block.call(stdout.lazy) - cmd_status = 0 - break - else - cmd_output << stdout.read - end - - cmd_output << err_reader.value if include_stderr - cmd_status = wait_thr.value.exitstatus - ensure - # When Popen3.open3 returns, the stderr reader gets closed, which causes - # an exception in the err_reader thread. Kill the thread before - # returning from Popen3.open3. - err_reader.kill - end - end - - [cmd_output, cmd_status] - end - end - end -end diff --git a/ruby/lib/gitlab/git/push_options.rb b/ruby/lib/gitlab/git/push_options.rb deleted file mode 100644 index a3829cc9d..000000000 --- a/ruby/lib/gitlab/git/push_options.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Git - class PushOptions - attr_accessor :options - - def initialize(options) - @options = options - end - - def env_data - return {} if options.empty? - - data = { - 'GIT_PUSH_OPTION_COUNT' => options.count.to_s - } - - options.each_with_index do |opt, index| - data["GIT_PUSH_OPTION_#{index}"] = opt - end - - data - end - end - end -end diff --git a/ruby/lib/gitlab/git/ref.rb b/ruby/lib/gitlab/git/ref.rb deleted file mode 100644 index e45bec404..000000000 --- a/ruby/lib/gitlab/git/ref.rb +++ /dev/null @@ -1,53 +0,0 @@ -# Gitaly note: JV: probably no RPC's here (just one interaction with Rugged). - -module Gitlab - module Git - class Ref - include Gitlab::EncodingHelper - - # Canonical refname, including `refs/heads|tags/` prefix - attr_reader :refname - - # Branch or tag name - # without "refs/tags|heads" prefix - attr_reader :name - - # Target sha. - # Usually it is commit sha but in case - # when tag reference on other tag it can be tag sha - attr_reader :target - - # Dereferenced target - # Commit object to which the Ref points to - attr_reader :dereferenced_target - - # Extract branch name from full ref path - # - # Ex. - # Ref.extract_branch_name('refs/heads/master') #=> 'master' - def self.extract_branch_name(str) - str.gsub(%r{\Arefs/heads/}, '') - end - - # Gitaly: this method will probably be migrated indirectly via its call sites. - def self.dereference_object(object) - object = object.target while object.is_a?(Rugged::Tag::Annotation) - - object - end - - def initialize(_repository, name, target, dereferenced_target) - @refname = name - @name = Gitlab::Git.ref_name(name) - @dereferenced_target = dereferenced_target - @target = if target.respond_to?(:oid) - target.oid - elsif target.respond_to?(:name) - target.name - elsif target.is_a? String - target - end - end - end - end -end diff --git a/ruby/lib/gitlab/git/repository.rb b/ruby/lib/gitlab/git/repository.rb deleted file mode 100644 index cbe5bde19..000000000 --- a/ruby/lib/gitlab/git/repository.rb +++ /dev/null @@ -1,282 +0,0 @@ -require 'securerandom' - -module Gitlab - module Git - # These are monkey patches on top of the vendored version of Repository. - class Repository - include Gitlab::Git::Popen - include Gitlab::EncodingHelper - include Gitlab::Utils::StrongMemoize - - GITALY_INTERNAL_URL = 'ssh://gitaly/internal.git'.freeze - RUGGED_KEY = :rugged_list - GIT_ALLOW_SHA_UPLOAD = 'uploadpack.allowAnySHA1InWant=true'.freeze - - NoRepository = Class.new(StandardError) - InvalidRef = Class.new(StandardError) - GitError = Class.new(StandardError) - - class << self - def from_gitaly(gitaly_repository, call) - new( - gitaly_repository, - GitalyServer.repo_path(call), - GitalyServer.gl_repository(call), - GitalyServer.repo_alt_dirs(call), - GitalyServer.feature_flags(call) - ) - end - - def from_gitaly_with_block(gitaly_repository, call) - repository = from_gitaly(gitaly_repository, call) - - result = yield repository - - repository.cleanup - - result - end - end - - attr_reader :path - - # Directory name of repo - attr_reader :name - - attr_reader :storage, :gl_repository, :gl_project_path, :relative_path - - def initialize(gitaly_repository, path, gl_repository, combined_alt_dirs = "", feature_flags = GitalyServer::FeatureFlags.new({})) - @gitaly_repository = gitaly_repository - - @alternate_object_directories = combined_alt_dirs - .split(File::PATH_SEPARATOR) - .map { |d| File.join(path, d) } - - @storage = gitaly_repository.storage_name - @relative_path = gitaly_repository.relative_path - @path = path - @gl_repository = gl_repository - @gl_project_path = gitaly_repository.gl_project_path - @feature_flags = feature_flags - end - - def ==(other) - [storage, relative_path] == [other.storage, other.relative_path] - end - - attr_reader :gitaly_repository - - attr_reader :alternate_object_directories - - def sort_branches(branches, sort_by) - case sort_by - when 'name' - branches.sort_by(&:name) - when 'updated_desc' - branches.sort do |a, b| - b.dereferenced_target.committed_date <=> a.dereferenced_target.committed_date - end - when 'updated_asc' - branches.sort do |a, b| - a.dereferenced_target.committed_date <=> b.dereferenced_target.committed_date - end - else - branches - end - end - - def exists? - File.exist?(File.join(path, 'refs')) - end - - def root_ref - @root_ref ||= discover_default_branch - end - - def rugged - @rugged ||= begin - # Open in bare mode, for a slight performance gain - # https://github.com/libgit2/rugged/blob/654ff2fe12041e09707ba0647307abcb6348a7fb/ext/rugged/rugged_repo.c#L276-L278 - Rugged::Repository.bare(path, alternates: alternate_object_directories).tap do |repo| - Thread.current[RUGGED_KEY] << repo if Thread.current[RUGGED_KEY] - end - end - rescue Rugged::RepositoryError, Rugged::OSError - raise NoRepository, 'no repository for such path' - end - - def branch_names - branches.map(&:name) - end - - def branches - branches_filter - end - - # Git repository can contains some hidden refs like: - # /refs/notes/* - # /refs/git-as-svn/* - # /refs/pulls/* - # This refs by default not visible in project page and not cloned to client side. - def has_visible_content? - strong_memoize(:has_visible_content) do - branches_filter(filter: :local).any? do |ref| - begin - ref.name && ref.target # ensures the branch is valid - - true - rescue Rugged::ReferenceError - false - end - end - end - end - - def tags - rugged.references.each("refs/tags/*").map do |ref| - message = nil - - if ref.target.is_a?(Rugged::Tag::Annotation) - tag_message = ref.target.message - - message = tag_message.chomp if tag_message.respond_to?(:chomp) - end - - target_commit = Gitlab::Git::Commit.find(self, ref.target) - Gitlab::Git::Tag.new(self, - name: ref.canonical_name, - target: ref.target, - target_commit: target_commit, - message: message) - end.sort_by(&:name) - end - - # Discovers the default branch based on the repository's available branches - # - # - If no branches are present, returns nil - # - If one branch is present, returns its name - # - If two or more branches are present, returns current HEAD or master or first branch - def discover_default_branch - names = branch_names - - return if names.empty? - - return names[0] if names.length == 1 - - if rugged_head - extracted_name = Ref.extract_branch_name(rugged_head.name) - - return extracted_name if names.include?(extracted_name) - end - - if names.include?('master') - 'master' - else - names[0] - end - end - - def with_repo_branch_commit(start_ref) - if empty? - yield nil - else - # Directly return the commit from this repository - yield commit(start_ref) - end - end - - # Directly find a branch with a simple name (e.g. master) - # - # force_reload causes a new Rugged repository to be instantiated - # - # This is to work around a bug in libgit2 that causes in-memory refs to - # be stale/invalid when packed-refs is changed. - # See https://gitlab.com/gitlab-org/gitlab-ce/issues/15392#note_14538333 - def find_branch(name, force_reload = false) - reload_rugged if force_reload - - rugged_ref = rugged.ref("refs/heads/" + name) - if rugged_ref - target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target) - Gitlab::Git::Branch.new(self, rugged_ref.canonical_name, rugged_ref.target, target_commit) - end - end - - # Returns true if the given branch exists - # - # name - The name of the branch as a String. - def branch_exists?(name) - rugged.branches.exists?(name) - - # If the branch name is invalid (e.g. ".foo") Rugged will raise an error. - # Whatever code calls this method shouldn't have to deal with that so - # instead we just return `false` (which is true since a branch doesn't - # exist when it has an invalid name). - rescue Rugged::ReferenceError - false - end - - def merge_base(from, to) - rugged.merge_base(from, to) - rescue Rugged::ReferenceError - nil - end - - # Lookup for rugged object by oid or ref name - def lookup(oid_or_ref_name) - rugged.rev_parse(oid_or_ref_name) - end - - # Return the object that +revspec+ points to. If +revspec+ is an - # annotated tag, then return the tag's target instead. - def rev_parse_target(revspec) - obj = rugged.rev_parse(revspec) - Ref.dereference_object(obj) - end - - def commit(ref = nil) - ref ||= root_ref - Gitlab::Git::Commit.find(self, ref) - end - - def empty? - !has_visible_content? - end - - def cleanup - # Opening a repository may be expensive, and we only need to close it - # if it's been open. - rugged&.close if defined?(@rugged) - end - - def head_symbolic_ref - head = rugged.ref('HEAD') - - return 'main' if head.type != :symbolic - - Ref.extract_branch_name(head.target_id) - end - - private - - def branches_filter(filter: nil, sort_by: nil) - branches = rugged.branches.each(filter).map do |rugged_ref| - begin - target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target) - Gitlab::Git::Branch.new(self, rugged_ref.canonical_name, rugged_ref.target, target_commit) - rescue Rugged::ReferenceError - # Omit invalid branch - end - end.compact - - sort_branches(branches, sort_by) - end - - def rugged_head - rugged.head - rescue Rugged::ReferenceError - nil - end - end - end -end diff --git a/ruby/lib/gitlab/git/tag.rb b/ruby/lib/gitlab/git/tag.rb deleted file mode 100644 index 1d7c8e5d2..000000000 --- a/ruby/lib/gitlab/git/tag.rb +++ /dev/null @@ -1,49 +0,0 @@ -require_relative 'ref' - -module Gitlab - module Git - class Tag < Ref - extend Gitlab::EncodingHelper - - attr_reader :object_sha, :repository - - SERIALIZE_KEYS = %i[name target target_commit message].freeze - - attr_accessor *SERIALIZE_KEYS # rubocop:disable Lint/AmbiguousOperator - - def initialize(repository, raw_tag) - @repository = repository - @raw_tag = raw_tag - - case raw_tag - when Hash - init_from_hash - when Gitaly::Tag - init_from_gitaly - end - - super(repository, name, target, target_commit) - end - - def init_from_hash - raw_tag = @raw_tag.symbolize_keys - - SERIALIZE_KEYS.each do |key| - send("#{key}=", raw_tag[key]) - end - end - - def init_from_gitaly - @name = encode!(@raw_tag.name.dup) - @target = @raw_tag.id - @message = @raw_tag.message.dup - - @target_commit = Gitlab::Git::Commit.decorate(repository, @raw_tag.target_commit) if @raw_tag.target_commit.present? - end - - def message - encode! @message - end - end - end -end diff --git a/ruby/lib/gitlab/git/user.rb b/ruby/lib/gitlab/git/user.rb deleted file mode 100644 index ebb317430..000000000 --- a/ruby/lib/gitlab/git/user.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Gitlab - module Git - class User - attr_reader :username, :name, :email, :gl_id - - def self.from_gitaly(gitaly_user) - new( - gitaly_user.gl_username, - Gitlab::EncodingHelper.encode!(gitaly_user.name), - Gitlab::EncodingHelper.encode!(gitaly_user.email), - gitaly_user.gl_id - ) - end - - def initialize(username, name, email, gl_id) - @username = username - @name = name - @email = email - @gl_id = gl_id - end - - def ==(other) - [username, name, email, gl_id] == [other.username, other.name, other.email, other.gl_id] - end - - def git_env(timestamp = nil) - { - 'GIT_COMMITTER_NAME' => name, - 'GIT_COMMITTER_EMAIL' => email, - 'GIT_COMMITTER_DATE' => timestamp ? "#{timestamp.seconds} +0000" : nil, - 'GL_ID' => Gitlab::GlId.gl_id(self) - }.reject { |_, v| v.nil? } - end - end - end -end |