Commit a5cfacc2 authored by Douwe Maan's avatar Douwe Maan
Browse files

Merge branch 'remove-rugged' into 'master'

Remove Gitlab::Git::Repository#rugged

See merge request gitlab-org/gitlab-ce!22039
parents 2d33579c a99bf447
...@@ -445,7 +445,6 @@ Style/Dir: ...@@ -445,7 +445,6 @@ Style/Dir:
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/EachWithObject: Style/EachWithObject:
Exclude: Exclude:
- 'config/initializers/gollum.rb'
- 'lib/expand_variables.rb' - 'lib/expand_variables.rb'
- 'lib/gitlab/ci/ansi2html.rb' - 'lib/gitlab/ci/ansi2html.rb'
- 'lib/gitlab/ee_compat_check.rb' - 'lib/gitlab/ee_compat_check.rb'
......
...@@ -80,11 +80,9 @@ gem 'gitlab_omniauth-ldap', '~> 2.0.4', require: 'omniauth-ldap' ...@@ -80,11 +80,9 @@ gem 'gitlab_omniauth-ldap', '~> 2.0.4', require: 'omniauth-ldap'
gem 'net-ldap' gem 'net-ldap'
# Git Wiki # Git Wiki
# Required manually in config/initializers/gollum.rb to control load order # Only used to compute wiki page slugs
gem 'gitlab-gollum-lib', '~> 4.2', require: false gem 'gitlab-gollum-lib', '~> 4.2', require: false
gem 'gitlab-gollum-rugged_adapter', '~> 0.4.4', require: false
# Language detection # Language detection
gem 'github-linguist', '~> 5.3.3', require: 'linguist' gem 'github-linguist', '~> 5.3.3', require: 'linguist'
...@@ -134,6 +132,7 @@ gem 'seed-fu', '~> 2.3.7' ...@@ -134,6 +132,7 @@ gem 'seed-fu', '~> 2.3.7'
gem 'html-pipeline', '~> 2.8' gem 'html-pipeline', '~> 2.8'
gem 'deckar01-task_list', '2.0.0' gem 'deckar01-task_list', '2.0.0'
gem 'gitlab-markup', '~> 1.6.4' gem 'gitlab-markup', '~> 1.6.4'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'redcarpet', '~> 3.4' gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17' gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
......
...@@ -295,9 +295,6 @@ GEM ...@@ -295,9 +295,6 @@ GEM
rouge (~> 3.1) rouge (~> 3.1)
sanitize (~> 4.6.4) sanitize (~> 4.6.4)
stringex (~> 2.6) stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15)
rugged (~> 0.25)
gitlab-grit (2.8.2) gitlab-grit (2.8.2)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
...@@ -1030,9 +1027,9 @@ DEPENDENCIES ...@@ -1030,9 +1027,9 @@ DEPENDENCIES
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.118.1) gitaly-proto (~> 0.118.1)
github-linguist (~> 5.3.3) github-linguist (~> 5.3.3)
github-markup (~> 1.7.0)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2) gitlab-gollum-lib (~> 4.2)
gitlab-gollum-rugged_adapter (~> 0.4.4)
gitlab-markup (~> 1.6.4) gitlab-markup (~> 1.6.4)
gitlab-styles (~> 2.4) gitlab-styles (~> 2.4)
gitlab_omniauth-ldap (~> 2.0.4) gitlab_omniauth-ldap (~> 2.0.4)
......
...@@ -298,9 +298,6 @@ GEM ...@@ -298,9 +298,6 @@ GEM
rouge (~> 3.1) rouge (~> 3.1)
sanitize (~> 4.6.4) sanitize (~> 4.6.4)
stringex (~> 2.6) stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15)
rugged (~> 0.25)
gitlab-grit (2.8.2) gitlab-grit (2.8.2)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
...@@ -1039,9 +1036,9 @@ DEPENDENCIES ...@@ -1039,9 +1036,9 @@ DEPENDENCIES
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.118.1) gitaly-proto (~> 0.118.1)
github-linguist (~> 5.3.3) github-linguist (~> 5.3.3)
github-markup (~> 1.7.0)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2) gitlab-gollum-lib (~> 4.2)
gitlab-gollum-rugged_adapter (~> 0.4.4)
gitlab-markup (~> 1.6.4) gitlab-markup (~> 1.6.4)
gitlab-styles (~> 2.4) gitlab-styles (~> 2.4)
gitlab_omniauth-ldap (~> 2.0.4) gitlab_omniauth-ldap (~> 2.0.4)
......
...@@ -58,7 +58,7 @@ def to_key ...@@ -58,7 +58,7 @@ def to_key
attr_reader :page attr_reader :page
# The attributes Hash used for storing and validating # The attributes Hash used for storing and validating
# new Page values before writing to the Gollum repository. # new Page values before writing to the raw repository.
attr_accessor :attributes attr_accessor :attributes
def hook_attrs def hook_attrs
...@@ -111,10 +111,7 @@ def directory ...@@ -111,10 +111,7 @@ def directory
# The processed/formatted content of this page. # The processed/formatted content of this page.
def formatted_content def formatted_content
# Assuming @page exists, nil formatted_data means we didn't load it @attributes[:formatted_content] ||= @wiki.page_formatted_data(@page)
# before hand (i.e. page was fetched by Gitaly), so we fetch it separately.
# If the page was fetched by Gollum, formatted_data would've been a String.
@attributes[:formatted_content] ||= @page&.formatted_data || @wiki.page_formatted_data(@page)
end end
# The markup format for the page. # The markup format for the page.
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
# that we can stub it for testing, as it is only called when metrics are # that we can stub it for testing, as it is only called when metrics are
# enabled. # enabled.
# #
# rubocop:disable Metrics/AbcSize
def instrument_classes(instrumentation) def instrument_classes(instrumentation)
instrumentation.instrument_instance_methods(Gitlab::Shell) instrumentation.instrument_instance_methods(Gitlab::Shell)
...@@ -48,16 +47,6 @@ def instrument_classes(instrumentation) ...@@ -48,16 +47,6 @@ def instrument_classes(instrumentation)
instrumentation.instrument_methods(Premailer::Adapter::Nokogiri) instrumentation.instrument_methods(Premailer::Adapter::Nokogiri)
instrumentation.instrument_instance_methods(Premailer::Adapter::Nokogiri) instrumentation.instrument_instance_methods(Premailer::Adapter::Nokogiri)
[
:Blame, :Branch, :BranchCollection, :Blob, :Commit, :Diff, :Repository,
:Tag, :TagCollection, :Tree
].each do |name|
const = Rugged.const_get(name)
instrumentation.instrument_methods(const)
instrumentation.instrument_instance_methods(const)
end
instrumentation.instrument_methods(Banzai::Renderer) instrumentation.instrument_methods(Banzai::Renderer)
instrumentation.instrument_methods(Banzai::Querying) instrumentation.instrument_methods(Banzai::Querying)
...@@ -101,7 +90,6 @@ def instrument_classes(instrumentation) ...@@ -101,7 +90,6 @@ def instrument_classes(instrumentation)
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159 # Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits) instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
end end
# rubocop:enable Metrics/AbcSize
# With prometheus enabled by default this breaks all specs # With prometheus enabled by default this breaks all specs
# that stubs methods using `any_instance_of` for the models reloaded here. # that stubs methods using `any_instance_of` for the models reloaded here.
......
# WARNING changes in this file must be manually propagated to gitaly-ruby.
#
# https://gitlab.com/gitlab-org/gitaly/blob/master/ruby/lib/gitlab/gollum.rb
module Gollum
GIT_ADAPTER = "rugged".freeze
end
require "gollum-lib"
module Gollum
class Page
def text_data(encoding = nil)
data = if raw_data.respond_to?(:encoding)
raw_data.force_encoding(encoding || Encoding::UTF_8)
else
raw_data
end
Gitlab::EncodingHelper.encode!(data)
end
end
end
Rails.application.configure do
config.after_initialize do
Gollum::Page.per_page = Kaminari.config.default_per_page
end
end
# GitLab Developers Guide to Working with Gitaly # GitLab Developers Guide to Working with Gitaly
[Gitaly](https://gitlab.com/gitlab-org/gitaly) is a high-level Git RPC service used by GitLab CE/EE, [Gitaly](https://gitlab.com/gitlab-org/gitaly) is a high-level Git RPC service used by GitLab CE/EE,
Workhorse and GitLab-Shell. All Rugged operations in GitLab CE/EE are currently being phased out to Workhorse and GitLab-Shell.
be replaced by Gitaly API calls.
Visit the [Gitaly Migration Board](https://gitlab.com/gitlab-org/gitaly/boards/331341) for current
status of the migration.
## Developing new Git features ## Developing new Git features
...@@ -52,57 +48,6 @@ comfortable writing Go code. ...@@ -52,57 +48,6 @@ comfortable writing Go code.
There is documentation for this approach in [the Gitaly There is documentation for this approach in [the Gitaly
repo](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md). repo](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md).
## Modifying existing Git features
If you modify existing Git features in `lib/gitlab/git` you need to make
sure the changes also work in Gitaly. Because we are still in the
migration process there are a number of subtle pitfalls. Features that
have been migrated have dual implementations (Gitaly and local). The
Gitaly implementation may or may not use a vendored (and therefore
possibly outdated) copy of the local implementation in `lib/gitlab/git`.
To avoid unexpected problems and conflicts, all changes to
`lib/gitlab/git` need to be approved by a member of the Gitaly team.
For the time being, while the Gitaly migration is still in progress,
there should be no Enterprise Edition-only Git code in
`lib/gitlab/git`. Also no mixins.
## Feature Flags
Gitaly makes heavy use of [feature flags](feature_flags.md).
Each Rugged-to-Gitaly migration goes through a [series of phases](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/MIGRATION_PROCESS.md):
* **Opt-In**: by default the Rugged implementation is used.
* Production instances can choose to enable the Gitaly endpoint by enabling the feature flag.
* For testing purposes, you may wish to enable all feature flags by default. This can be done by exporting the following
environment variable: `GITALY_FEATURE_DEFAULT_ON=1`.
* On developer instances (ie, when `Rails.env.development?` is true), the Gitaly endpoint
is enabled by default, but can be _disabled_ using feature flags.
* **Opt-Out**: by default, the Gitaly endpoint is used, but the feature can be explicitly disabled using the feature flag.
* **Mandatory**: The migration is complete and cannot be disabled. The old codepath is removed.
### Enabling and Disabling Feature
In the Rails console, type:
```ruby
Feature.enable(:gitaly_feature_name)
Feature.disable(:gitaly_feature_name)
```
Where `gitaly_feature_name` is the name of the Gitaly feature. This can be determined by finding the appropriate
`gitaly_migrate` code block, for example:
```ruby
gitaly_migrate(:tag_names) do
...
end
```
Since Gitaly features are always prefixed with `gitaly_`, the name of the feature flag in this case would be `gitaly_tag_names`.
## Gitaly-Related Test Failures ## Gitaly-Related Test Failures
If your test-suite is failing with Gitaly issues, as a first step, try running: If your test-suite is failing with Gitaly issues, as a first step, try running:
......
...@@ -69,7 +69,7 @@ The easiest way to check if a method has been instrumented is to check its ...@@ -69,7 +69,7 @@ The easiest way to check if a method has been instrumented is to check its
source location. For example: source location. For example:
```ruby ```ruby
method = Rugged::TagCollection.instance_method(:[]) method = Banzai::Renderer.method(:render)
method.source_location method.source_location
``` ```
...@@ -82,7 +82,7 @@ method (along with its source location), this is easier than running the above ...@@ -82,7 +82,7 @@ method (along with its source location), this is easier than running the above
Ruby code. In case of the above snippet you'd run the following: Ruby code. In case of the above snippet you'd run the following:
``` ```
$ Rugged::TagCollection#[] $ Banzai::Renderer.render
``` ```
This will print out something along the lines of: This will print out something along the lines of:
......
...@@ -53,9 +53,6 @@ def find(repo, commit_id = "HEAD") ...@@ -53,9 +53,6 @@ def find(repo, commit_id = "HEAD")
# Already a commit? # Already a commit?
return commit_id if commit_id.is_a?(Gitlab::Git::Commit) return commit_id if commit_id.is_a?(Gitlab::Git::Commit)
# A rugged reference?
commit_id = Gitlab::Git::Ref.dereference_object(commit_id)
# Some weird thing? # Some weird thing?
return nil unless commit_id.is_a?(String) return nil unless commit_id.is_a?(String)
...@@ -127,8 +124,6 @@ def between(repo, base, head) ...@@ -127,8 +124,6 @@ def between(repo, base, head)
# :topo, or any combination of them (in an array). Commit ordering types # :topo, or any combination of them (in an array). Commit ordering types
# are documented here: # are documented here:
# http://www.rubydoc.info/github/libgit2/rugged/Rugged#SORT_NONE-constant) # http://www.rubydoc.info/github/libgit2/rugged/Rugged#SORT_NONE-constant)
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/326
def find_all(repo, options = {}) def find_all(repo, options = {})
repo.wrapped_gitaly_errors do repo.wrapped_gitaly_errors do
Gitlab::GitalyClient::CommitService.new(repo).find_all_commits(options) Gitlab::GitalyClient::CommitService.new(repo).find_all_commits(options)
...@@ -328,7 +323,6 @@ def tree_entry(path) ...@@ -328,7 +323,6 @@ def tree_entry(path)
entry = @repository.gitaly_commit_client.tree_entry(id, path, 1) entry = @repository.gitaly_commit_client.tree_entry(id, path, 1)
return unless entry return unless entry
# To be compatible with the rugged format
entry = entry.to_h entry = entry.to_h
entry.delete(:data) entry.delete(:data)
entry[:name] = File.basename(path) entry[:name] = File.basename(path)
...@@ -346,8 +340,8 @@ def to_gitaly_commit ...@@ -346,8 +340,8 @@ def to_gitaly_commit
subject: message_split[0] ? message_split[0].chomp.b : "", subject: message_split[0] ? message_split[0].chomp.b : "",
body: raw_commit.message.b, body: raw_commit.message.b,
parent_ids: raw_commit.parent_ids, parent_ids: raw_commit.parent_ids,
author: gitaly_commit_author_from_rugged(raw_commit.author), author: gitaly_commit_author_from_raw(raw_commit.author),
committer: gitaly_commit_author_from_rugged(raw_commit.committer) committer: gitaly_commit_author_from_raw(raw_commit.committer)
) )
end end
...@@ -381,7 +375,7 @@ def serialize_keys ...@@ -381,7 +375,7 @@ def serialize_keys
SERIALIZE_KEYS SERIALIZE_KEYS
end end
def gitaly_commit_author_from_rugged(author_or_committer) def gitaly_commit_author_from_raw(author_or_committer)
Gitaly::CommitAuthor.new( Gitaly::CommitAuthor.new(
name: author_or_committer[:name].b, name: author_or_committer[:name].b,
email: author_or_committer[:email].b, email: author_or_committer[:email].b,
......
# Gitaly note: JV: probably no RPC's here (just one interaction with Rugged).
module Gitlab module Gitlab
module Git module Git
class Ref class Ref
...@@ -26,13 +24,6 @@ def self.extract_branch_name(str) ...@@ -26,13 +24,6 @@ def self.extract_branch_name(str)
str.gsub(%r{\Arefs/heads/}, '') str.gsub(%r{\Arefs/heads/}, '')
end 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) def initialize(repository, name, target, dereferenced_target)
@name = Gitlab::Git.ref_name(name) @name = Gitlab::Git.ref_name(name)
@dereferenced_target = dereferenced_target @dereferenced_target = dereferenced_target
......
...@@ -9,14 +9,6 @@ class Repository ...@@ -9,14 +9,6 @@ class Repository
include Gitlab::EncodingHelper include Gitlab::EncodingHelper
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
ALLOWED_OBJECT_DIRECTORIES_VARIABLES = %w[
GIT_OBJECT_DIRECTORY
GIT_ALTERNATE_OBJECT_DIRECTORIES
].freeze
ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES = %w[
GIT_OBJECT_DIRECTORY_RELATIVE
GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE
].freeze
SEARCH_CONTEXT_LINES = 3 SEARCH_CONTEXT_LINES = 3
REV_LIST_COMMIT_LIMIT = 2_000 REV_LIST_COMMIT_LIMIT = 2_000
# In https://gitlab.com/gitlab-org/gitaly/merge_requests/698 # In https://gitlab.com/gitlab-org/gitaly/merge_requests/698
...@@ -104,15 +96,6 @@ def root_ref ...@@ -104,15 +96,6 @@ def root_ref
raise Gitlab::Git::CommandError.new(e.message) raise Gitlab::Git::CommandError.new(e.message)
end end
# This method will be removed when Gitaly reaches v1.1.
def rugged
circuit_breaker.perform do
Rugged::Repository.new(path, alternates: alternate_object_directories)
end
rescue Rugged::RepositoryError, Rugged::OSError
raise NoRepository.new('no repository for such path')
end
def circuit_breaker def circuit_breaker
@circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(storage) @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(storage)
end end
...@@ -638,20 +621,6 @@ def find_remote_root_ref(remote_name) ...@@ -638,20 +621,6 @@ def find_remote_root_ref(remote_name)
end end
end end
AUTOCRLF_VALUES = {
"true" => true,
"false" => false,
"input" => :input
}.freeze
def autocrlf
AUTOCRLF_VALUES[rugged.config['core.autocrlf']]
end
def autocrlf=(value)
rugged.config['core.autocrlf'] = AUTOCRLF_VALUES.invert[value]
end
# Returns result like "git ls-files" , recursive and full file path # Returns result like "git ls-files" , recursive and full file path
# #
# Ex. # Ex.
...@@ -1024,14 +993,6 @@ def gitaly_submodule_url_for(ref, path) ...@@ -1024,14 +993,6 @@ def gitaly_submodule_url_for(ref, path)
found_module && found_module['url'] found_module && found_module['url']
end end
def alternate_object_directories
relative_object_directories.map { |d| File.join(path, d) }
end
def relative_object_directories
Gitlab::Git::HookEnv.all(gl_repository).values_at(*ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES).flatten.compact
end
# Returns true if the given ref name exists # Returns true if the given ref name exists
# #
# Ref names must start with `refs/`. # Ref names must start with `refs/`.
......
# We only need Gollum::Page so let's not load all of gollum-lib.
require 'gollum-lib/pagination'
require 'gollum-lib/wiki'
require 'gollum-lib/page'
module Gitlab module Gitlab
module Git module Git
class Wiki class Wiki
DuplicatePageError = Class.new(StandardError) DuplicatePageError = Class.new(StandardError)
OperationError = Class.new(StandardError) OperationError = Class.new(StandardError)
DEFAULT_PAGINATION = Kaminari.config.default_per_page
CommitDetails = Struct.new(:user_id, :username, :name, :email, :message) do CommitDetails = Struct.new(:user_id, :username, :name, :email, :message) do
def to_h def to_h
{ user_id: user_id, username: username, name: name, email: email, message: message } { user_id: user_id, username: username, name: name, email: email, message: message }
...@@ -74,7 +81,7 @@ def page_versions(page_path, options = {}) ...@@ -74,7 +81,7 @@ def page_versions(page_path, options = {})
# Gitaly uses gollum-lib to get the versions. Gollum defaults to 20 # Gitaly uses gollum-lib to get the versions. Gollum defaults to 20
# per page, but also fetches 20 if `limit` or `per_page` < 20. # per page, but also fetches 20 if `limit` or `per_page` < 20.
# Slicing returns an array with the expected number of items. # Slicing returns an array with the expected number of items.
slice_bound = options[:limit] || options[:per_page] || Gollum::Page.per_page slice_bound = options[:limit] || options[:per_page] || DEFAULT_PAGINATION
versions[0..slice_bound] versions[0..slice_bound]
end end
...@@ -104,26 +111,6 @@ def page_formatted_data(title:, dir: nil, version: nil) ...@@ -104,26 +111,6 @@ def page_formatted_data(title:, dir: nil, version: nil)
private private
def new_page(gollum_page)
Gitlab::Git::WikiPage.new(gollum_page, new_version(gollum_page, gollum_page.version.id))
end
def new_version(gollum_page, commit_id)
Gitlab::Git::WikiPageVersion.new(version(commit_id), gollum_page&.format)
end
def version(commit_id)
commit_find_proc = -> { Gitlab::Git::Commit.find(@repository, commit_id) }
Gitlab::SafeRequestStore.fetch([:wiki_version_commit, commit_id]) { commit_find_proc.call }
end
def assert_type!(object, klass)
unless object.is_a?(klass)
raise ArgumentError, "expected a #{klass}, got #{object.inspect}"
end
end
def gitaly_wiki_client def gitaly_wiki_client
@gitaly_wiki_client ||= Gitlab::GitalyClient::WikiService.new(@repository) @gitaly_wiki_client ||= Gitlab::GitalyClient::WikiService.new(@repository)
end end
......
...@@ -3,17 +3,12 @@ module Git ...@@ -3,17 +3,12 @@ module Git
class WikiFile class WikiFile
attr_reader :mime_type, :raw_data, :name, :path attr_reader :mime_type, :raw_data, :name, :path
# This class is meant to be serializable so that it can be constructed # This class wraps Gitlab::GitalyClient::WikiFile
# by Gitaly and sent over the network to GitLab. def initialize(gitaly_file)
# @mime_type = gitaly_file.mime_type
# Because Gollum::File is not serializable we must get all the data from @raw_data = gitaly_file.raw_data
# 'gollum_file' during initialization, and NOT store it in an instance @name = gitaly_file.name
# variable. @path = gitaly_file.path
def initialize(gollum_file)
@mime_type = gollum_file.mime_type
@raw_data = gollum_file.raw_data
@name = gollum_file.name
@path = gollum_file.path
end end
end end
end end
......
...@@ -3,25 +3,15 @@ module Git ...@@ -3,25 +3,15 @@ module Git
class WikiPage class WikiPage
attr_reader :url_path, :title, :format, :path, :version, :raw_data, :name, :text_data, :historical, :formatted_data attr_reader :url_path, :title, :format, :path, :version, :raw_data, :name, :text_data, :historical, :formatted_data
# This class is meant to be serializable so that it can be constructed # This class abstracts away Gitlab::GitalyClient::WikiPage