Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeger-Jan van de Weg <git@zjvandeweg.nl>2018-08-03 16:24:26 +0300
committerStan Hu <stanhu@gmail.com>2018-10-13 03:17:30 +0300
commit399056ed783e12337a9c47b06b4aae021198f1cd (patch)
tree21645fa92b300735c5431608e17f3e34b34ce653 /lib/gitlab/blob_helper.rb
parenta5ecb5bbdac05c3b1a96ecb918ce6a4ceed37d75 (diff)
Remove dependencies on Linguist
This saves about 128 MB of baseline RAM usage per Unicorn and Sidekiq process (!). Linguist wasn't detecting languages anymore from CE/EE since 9ae8b57467ac8b38f1fa9020a466d94a93cbb9dd. However, Linguist::BlobHelper was still being depended on by BlobLike and others. This removes the Linguist gem, given it isn't required anymore. EscapeUtils were pulled in as dependency, but given Banzai depends on it, it is now added explicitly. Previously, Linguist was used to detect the best ACE mode. Instead, we rely on ACE to guess the best mode based on the file extension.
Diffstat (limited to 'lib/gitlab/blob_helper.rb')
-rw-r--r--lib/gitlab/blob_helper.rb145
1 files changed, 145 insertions, 0 deletions
diff --git a/lib/gitlab/blob_helper.rb b/lib/gitlab/blob_helper.rb
new file mode 100644
index 00000000000..9b3b383b0c8
--- /dev/null
+++ b/lib/gitlab/blob_helper.rb
@@ -0,0 +1,145 @@
+# This has been extracted from https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb
+module Gitlab
+ module BlobHelper
+ def extname
+ File.extname(name.to_s)
+ end
+
+ def known_extension?
+ LanguageData.extensions.include?(extname)
+ end
+
+ def viewable?
+ !large? && text?
+ end
+
+ MEGABYTE = 1024 * 1024
+
+ def large?
+ size.to_i > MEGABYTE
+ end
+
+ def binary?
+ # Large blobs aren't even loaded into memory
+ if data.nil?
+ true
+
+ # Treat blank files as text
+ elsif data == ""
+ false
+
+ # Charlock doesn't know what to think
+ elsif encoding.nil?
+ true
+
+ # If Charlock says its binary
+ else
+ detect_encoding[:type] == :binary
+ end
+ end
+
+ def text?
+ !binary?
+ end
+
+ def image?
+ ['.png', '.jpg', '.jpeg', '.gif'].include?(extname.downcase)
+ end
+
+ # Internal: Lookup mime type for extension.
+ #
+ # Returns a MIME::Type
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def _mime_type
+ if defined? @_mime_type
+ @_mime_type
+ else
+ guesses = ::MIME::Types.type_for(extname.to_s)
+
+ # Prefer text mime types over binary
+ @_mime_type = guesses.detect { |type| type.ascii? } || guesses.first
+ end
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+
+ # Public: Get the actual blob mime type
+ #
+ # Examples
+ #
+ # # => 'text/plain'
+ # # => 'text/html'
+ #
+ # Returns a mime type String.
+ def mime_type
+ _mime_type ? _mime_type.to_s : 'text/plain'
+ end
+
+ def binary_mime_type?
+ _mime_type ? _mime_type.binary? : false
+ end
+
+ def lines
+ @lines ||=
+ if viewable? && data
+ # `data` is usually encoded as ASCII-8BIT even when the content has
+ # been detected as a different encoding. However, we are not allowed
+ # to change the encoding of `data` because we've made the implicit
+ # guarantee that each entry in `lines` is encoded the same way as
+ # `data`.
+ #
+ # Instead, we re-encode each possible newline sequence as the
+ # detected encoding, then force them back to the encoding of `data`
+ # (usually a binary encoding like ASCII-8BIT). This means that the
+ # byte sequence will match how newlines are likely encoded in the
+ # file, but we don't have to change the encoding of `data` as far as
+ # Ruby is concerned. This allows us to correctly parse out each line
+ # without changing the encoding of `data`, and
+ # also--importantly--without having to duplicate many (potentially
+ # large) strings.
+ begin
+ data.split(encoded_newlines_re, -1)
+ rescue Encoding::ConverterNotFoundError
+ # The data is not splittable in the detected encoding. Assume it's
+ # one big line.
+ [data]
+ end
+ else
+ []
+ end
+ end
+
+ def content_type
+ # rubocop:disable Style/MultilineTernaryOperator
+ # rubocop:disable Style/NestedTernaryOperator
+ @content_type ||= binary_mime_type? || binary? ? mime_type :
+ (encoding ? "text/plain; charset=#{encoding.downcase}" : "text/plain")
+ # rubocop:enable Style/NestedTernaryOperator
+ # rubocop:enable Style/MultilineTernaryOperator
+ end
+
+ def encoded_newlines_re
+ @encoded_newlines_re ||=
+ Regexp.union(["\r\n", "\r", "\n"].map { |nl| nl.encode(ruby_encoding, "ASCII-8BIT").force_encoding(data.encoding) })
+ end
+
+ def ruby_encoding
+ if hash = detect_encoding
+ hash[:ruby_encoding]
+ end
+ end
+
+ def encoding
+ if hash = detect_encoding
+ hash[:encoding]
+ end
+ end
+
+ def detect_encoding
+ @detect_encoding ||= CharlockHolmes::EncodingDetector.new.detect(data) if data # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def empty?
+ data.nil? || data == ""
+ end
+ end
+end