2018-11-09 18:39:43 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
module Gitlab
|
|
|
|
module Git
|
|
|
|
class Wiki
|
2018-10-30 13:37:40 +00:00
|
|
|
include Gitlab::Git::WrapsGitalyErrors
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
DuplicatePageError = Class.new(StandardError)
|
|
|
|
|
2018-10-02 03:21:46 +00:00
|
|
|
DEFAULT_PAGINATION = Kaminari.config.default_per_page
|
|
|
|
|
2018-04-18 17:50:56 +00:00
|
|
|
CommitDetails = Struct.new(:user_id, :username, :name, :email, :message) do
|
2017-10-03 16:58:33 +00:00
|
|
|
def to_h
|
2018-04-18 17:50:56 +00:00
|
|
|
{ user_id: user_id, username: username, name: name, email: email, message: message }
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-15 17:00:59 +00:00
|
|
|
# GollumSlug inlines just enough knowledge from Gollum::Page to generate a
|
|
|
|
# slug, which is used when previewing pages that haven't been persisted
|
|
|
|
class GollumSlug
|
|
|
|
class << self
|
|
|
|
def cname(name, char_white_sub = '-', char_other_sub = '-')
|
|
|
|
if name.respond_to?(:gsub)
|
|
|
|
name.gsub(/\s/, char_white_sub).gsub(/[<>+]/, char_other_sub)
|
|
|
|
else
|
|
|
|
''
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-15 17:34:55 +00:00
|
|
|
def format_to_ext(format)
|
|
|
|
format == :markdown ? "md" : format.to_s
|
|
|
|
end
|
|
|
|
|
|
|
|
def canonicalize_filename(filename)
|
|
|
|
::File.basename(filename, ::File.extname(filename)).tr('-', ' ')
|
|
|
|
end
|
|
|
|
|
2018-10-15 17:00:59 +00:00
|
|
|
def generate(title, format)
|
2018-10-15 17:34:55 +00:00
|
|
|
ext = format_to_ext(format.to_sym)
|
|
|
|
name = cname(title) + '.' + ext
|
|
|
|
canonical_name = canonicalize_filename(name)
|
2018-10-15 17:00:59 +00:00
|
|
|
|
|
|
|
path =
|
2018-10-15 17:34:55 +00:00
|
|
|
if name.include?('/')
|
|
|
|
name.sub(%r{/[^/]+$}, '/')
|
2018-10-15 17:00:59 +00:00
|
|
|
else
|
|
|
|
''
|
|
|
|
end
|
|
|
|
|
2018-10-15 17:34:55 +00:00
|
|
|
path + cname(canonical_name, '-', '-')
|
2018-10-15 17:00:59 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-15 01:52:07 +00:00
|
|
|
attr_reader :repository
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
def self.default_ref
|
|
|
|
'master'
|
|
|
|
end
|
|
|
|
|
|
|
|
# Initialize with a Gitlab::Git::Repository instance
|
|
|
|
def initialize(repository)
|
|
|
|
@repository = repository
|
|
|
|
end
|
|
|
|
|
|
|
|
def repository_exists?
|
|
|
|
@repository.exists?
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_page(name, format, content, commit_details)
|
2018-10-30 13:37:40 +00:00
|
|
|
wrapped_gitaly_errors do
|
2018-06-18 08:19:11 +00:00
|
|
|
gitaly_write_page(name, format, content, commit_details)
|
2017-10-13 13:11:53 +00:00
|
|
|
end
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def delete_page(page_path, commit_details)
|
2018-10-30 13:37:40 +00:00
|
|
|
wrapped_gitaly_errors do
|
2018-06-18 08:19:11 +00:00
|
|
|
gitaly_delete_page(page_path, commit_details)
|
2017-10-31 10:38:15 +00:00
|
|
|
end
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def update_page(page_path, title, format, content, commit_details)
|
2018-10-30 13:37:40 +00:00
|
|
|
wrapped_gitaly_errors do
|
2018-06-18 08:19:11 +00:00
|
|
|
gitaly_update_page(page_path, title, format, content, commit_details)
|
2017-11-02 14:08:39 +00:00
|
|
|
end
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
2019-04-25 04:19:07 +00:00
|
|
|
def list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
|
2018-10-30 13:37:40 +00:00
|
|
|
wrapped_gitaly_errors do
|
2019-04-25 04:19:07 +00:00
|
|
|
gitaly_list_pages(
|
|
|
|
limit: limit,
|
|
|
|
sort: sort,
|
|
|
|
direction_desc: direction_desc,
|
|
|
|
load_content: load_content
|
|
|
|
)
|
2017-11-09 23:27:00 +00:00
|
|
|
end
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def page(title:, version: nil, dir: nil)
|
2018-10-30 13:37:40 +00:00
|
|
|
wrapped_gitaly_errors do
|
2018-06-18 08:19:11 +00:00
|
|
|
gitaly_find_page(title: title, version: version, dir: dir)
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def file(name, version)
|
2018-10-30 13:37:40 +00:00
|
|
|
wrapped_gitaly_errors do
|
2018-06-18 08:19:11 +00:00
|
|
|
gitaly_find_file(name, version)
|
2017-10-23 20:12:11 +00:00
|
|
|
end
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
2017-11-17 11:48:32 +00:00
|
|
|
# options:
|
|
|
|
# :page - The Integer page number.
|
|
|
|
# :per_page - The number of items per page.
|
|
|
|
# :limit - Total number of items to return.
|
|
|
|
def page_versions(page_path, options = {})
|
2018-10-30 13:37:40 +00:00
|
|
|
versions = wrapped_gitaly_errors do
|
2018-06-18 08:19:11 +00:00
|
|
|
gitaly_wiki_client.page_versions(page_path, options)
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
2018-06-18 08:19:11 +00:00
|
|
|
|
|
|
|
# Gitaly uses gollum-lib to get the versions. Gollum defaults to 20
|
|
|
|
# per page, but also fetches 20 if `limit` or `per_page` < 20.
|
|
|
|
# Slicing returns an array with the expected number of items.
|
2018-10-02 03:21:46 +00:00
|
|
|
slice_bound = options[:limit] || options[:per_page] || DEFAULT_PAGINATION
|
2018-06-18 08:19:11 +00:00
|
|
|
versions[0..slice_bound]
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
2017-11-17 11:48:32 +00:00
|
|
|
def count_page_versions(page_path)
|
|
|
|
@repository.count_commits(ref: 'HEAD', path: page_path)
|
|
|
|
end
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
def preview_slug(title, format)
|
2018-10-15 17:00:59 +00:00
|
|
|
GollumSlug.generate(title, format)
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2017-10-13 13:11:53 +00:00
|
|
|
def gitaly_wiki_client
|
|
|
|
@gitaly_wiki_client ||= Gitlab::GitalyClient::WikiService.new(@repository)
|
|
|
|
end
|
|
|
|
|
|
|
|
def gitaly_write_page(name, format, content, commit_details)
|
|
|
|
gitaly_wiki_client.write_page(name, format, content, commit_details)
|
|
|
|
end
|
2017-10-31 10:38:15 +00:00
|
|
|
|
2017-11-02 14:08:39 +00:00
|
|
|
def gitaly_update_page(page_path, title, format, content, commit_details)
|
|
|
|
gitaly_wiki_client.update_page(page_path, title, format, content, commit_details)
|
|
|
|
end
|
|
|
|
|
2017-10-31 10:38:15 +00:00
|
|
|
def gitaly_delete_page(page_path, commit_details)
|
|
|
|
gitaly_wiki_client.delete_page(page_path, commit_details)
|
|
|
|
end
|
2017-10-19 14:18:26 +00:00
|
|
|
|
|
|
|
def gitaly_find_page(title:, version: nil, dir: nil)
|
|
|
|
wiki_page, version = gitaly_wiki_client.find_page(title: title, version: version, dir: dir)
|
|
|
|
return unless wiki_page
|
|
|
|
|
|
|
|
Gitlab::Git::WikiPage.new(wiki_page, version)
|
2020-10-07 21:08:21 +00:00
|
|
|
rescue GRPC::InvalidArgument
|
|
|
|
nil
|
2017-10-19 14:18:26 +00:00
|
|
|
end
|
2017-10-23 20:12:11 +00:00
|
|
|
|
|
|
|
def gitaly_find_file(name, version)
|
|
|
|
wiki_file = gitaly_wiki_client.find_file(name, version)
|
|
|
|
return unless wiki_file
|
|
|
|
|
|
|
|
Gitlab::Git::WikiFile.new(wiki_file)
|
|
|
|
end
|
2017-11-09 23:27:00 +00:00
|
|
|
|
2019-04-25 04:19:07 +00:00
|
|
|
def gitaly_list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
|
|
|
|
params = { limit: limit, sort: sort, direction_desc: direction_desc }
|
|
|
|
|
|
|
|
gitaly_pages =
|
|
|
|
if load_content
|
2020-10-06 12:08:38 +00:00
|
|
|
gitaly_wiki_client.load_all_pages(**params)
|
2019-04-25 04:19:07 +00:00
|
|
|
else
|
2020-10-06 12:08:38 +00:00
|
|
|
gitaly_wiki_client.list_all_pages(**params)
|
2019-04-25 04:19:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
gitaly_pages.map do |wiki_page, version|
|
2017-11-09 23:27:00 +00:00
|
|
|
Gitlab::Git::WikiPage.new(wiki_page, version)
|
|
|
|
end
|
|
|
|
end
|
2017-10-03 16:58:33 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|