1# External dependencies of Gitlab::Git
2require 'rugged'
3require 'linguist/blob_helper'
4require 'securerandom'
5
6# Ruby on Rails mix-ins that GitLab::Git code relies on
7require 'active_support/core_ext/object/blank'
8require 'active_support/core_ext/numeric/bytes'
9require 'active_support/core_ext/numeric/time'
10require 'active_support/core_ext/integer/time'
11require 'active_support/core_ext/module/delegation'
12require 'active_support/core_ext/enumerable'
13
14require_relative 'git_logger.rb'
15require_relative 'rails_logger.rb'
16require_relative 'gollum.rb'
17require_relative 'config.rb'
18
19dir = __dir__
20
21# Some later requires are order-sensitive. Manually require whatever we need.
22require_relative "#{dir}/encoding_helper.rb"
23require_relative "#{dir}/utils/strong_memoize.rb"
24require_relative "#{dir}/git/remote_repository.rb"
25require_relative "#{dir}/git/popen.rb"
26
27# Require all .rb files we can find in the gitlab lib directory
28Dir["#{dir}/**/*.rb"].sort.each do |ruby_file|
29  require File.expand_path(ruby_file)
30end
31
32class String
33  # Because we are not rendering HTML, this is a no-op in gitaly-ruby.
34  def html_safe
35    self
36  end
37end
38
39module Gitlab
40  module Git
41    # The ID of empty tree.
42    # See http://stackoverflow.com/a/40884093/1856239 and
43    # https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012
44    EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze
45    BLANK_SHA = ('0' * 40).freeze
46    TAG_REF_PREFIX = "refs/tags/".freeze
47    BRANCH_REF_PREFIX = "refs/heads/".freeze
48
49    BaseError = Class.new(StandardError)
50    CommandError = Class.new(BaseError)
51    CommitError = Class.new(BaseError)
52    OSError = Class.new(BaseError)
53    UnknownRef = Class.new(BaseError)
54    PreReceiveError = Class.new(BaseError)
55    PatchError = Class.new(BaseError)
56
57    class << self
58      include Gitlab::EncodingHelper
59
60      def ref_name(ref)
61        encode!(ref).sub(%r{\Arefs/(tags|heads|remotes)/}, '')
62      end
63
64      def branch_name(ref)
65        ref = ref.to_s
66        self.ref_name(ref) if self.branch_ref?(ref)
67      end
68
69      def committer_hash(email:, name:, timestamp: nil)
70        return if email.nil? || name.nil?
71
72        # Git strips newlines and angle brackets silently.
73        # libgit2/Rugged doesn't, but aborts if angle brackets are present.
74        # See upstream issue https://github.com/libgit2/libgit2/issues/5342
75        email = email.delete("\n<>")
76        name = name.delete("\n<>")
77        time = timestamp ? Time.at(timestamp.seconds, timestamp.nanos, :nsec, in: "+00:00") : Time.now
78
79        {
80          email: email,
81          name: name,
82          time: time
83        }
84      end
85
86      def tag_name(ref)
87        ref = ref.to_s
88        self.ref_name(ref) if self.tag_ref?(ref)
89      end
90
91      def tag_ref?(ref)
92        ref.start_with?(TAG_REF_PREFIX)
93      end
94
95      def branch_ref?(ref)
96        ref.start_with?(BRANCH_REF_PREFIX)
97      end
98
99      def blank_ref?(ref)
100        ref == BLANK_SHA
101      end
102
103      def version
104        Gitlab::Git::Version.git_version
105      end
106
107      def diff_line_code(file_path, new_line_position, old_line_position)
108        "#{Digest::SHA1.hexdigest(file_path)}_#{old_line_position}_#{new_line_position}"
109      end
110
111      def shas_eql?(sha1, sha2)
112        return false if sha1.nil? || sha2.nil?
113        return false unless sha1.class == sha2.class
114
115        # If either of the shas is below the minimum length, we cannot be sure
116        # that they actually refer to the same commit because of hash collision.
117        length = [sha1.length, sha2.length].min
118        return false if length < Gitlab::Git::Commit::MIN_SHA_LENGTH
119
120        sha1[0, length] == sha2[0, length]
121      end
122    end
123  end
124end
125
126module Gitlab
127  module GlId
128    def self.gl_id(user)
129      user.gl_id
130    end
131
132    def self.gl_id_from_id_value(id)
133      "user-#{id}"
134    end
135  end
136end
137