2018-03-26 09:16:01 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-04-09 11:35:26 +00:00
|
|
|
class ProjectWiki
|
|
|
|
include Gitlab::ShellAdapter
|
2017-07-22 00:37:22 +00:00
|
|
|
include Storage::LegacyProjectWiki
|
2014-04-09 11:35:26 +00:00
|
|
|
|
|
|
|
MARKUPS = {
|
2016-02-28 12:11:43 +00:00
|
|
|
'Markdown' => :markdown,
|
2014-08-22 10:33:58 +00:00
|
|
|
'RDoc' => :rdoc,
|
2020-01-16 03:08:47 +00:00
|
|
|
'AsciiDoc' => :asciidoc,
|
|
|
|
'Org' => :org
|
2017-02-21 23:32:18 +00:00
|
|
|
}.freeze unless defined?(MARKUPS)
|
2014-04-09 11:35:26 +00:00
|
|
|
|
2017-03-01 11:00:37 +00:00
|
|
|
CouldNotCreateWikiError = Class.new(StandardError)
|
2018-03-26 09:16:01 +00:00
|
|
|
SIDEBAR = '_sidebar'
|
2014-04-09 11:35:26 +00:00
|
|
|
|
2019-04-04 16:28:56 +00:00
|
|
|
TITLE_ORDER = 'title'
|
|
|
|
CREATED_AT_ORDER = 'created_at'
|
|
|
|
DIRECTION_DESC = 'desc'
|
|
|
|
DIRECTION_ASC = 'asc'
|
|
|
|
|
2014-04-09 11:35:26 +00:00
|
|
|
# Returns a string describing what went wrong after
|
|
|
|
# an operation fails.
|
|
|
|
attr_reader :error_message
|
2016-01-22 09:24:38 +00:00
|
|
|
attr_reader :project
|
2014-04-09 11:35:26 +00:00
|
|
|
|
|
|
|
def initialize(project, user = nil)
|
|
|
|
@project = project
|
|
|
|
@user = user
|
|
|
|
end
|
|
|
|
|
2018-04-13 10:57:19 +00:00
|
|
|
delegate :repository_storage, :hashed_storage?, to: :project
|
2017-02-22 22:35:08 +00:00
|
|
|
|
2014-04-09 11:35:26 +00:00
|
|
|
def path
|
|
|
|
@project.path + '.wiki'
|
|
|
|
end
|
|
|
|
|
2017-07-22 00:37:22 +00:00
|
|
|
def full_path
|
2017-07-20 09:34:09 +00:00
|
|
|
@project.full_path + '.wiki'
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
2017-07-22 00:37:22 +00:00
|
|
|
# @deprecated use full_path when you need it for an URL route or disk_path when you want to point to the filesystem
|
|
|
|
alias_method :path_with_namespace, :full_path
|
|
|
|
|
2016-05-13 07:21:01 +00:00
|
|
|
def web_url
|
2017-06-29 17:06:35 +00:00
|
|
|
Gitlab::Routing.url_helpers.project_wiki_url(@project, :home)
|
2016-05-13 07:21:01 +00:00
|
|
|
end
|
|
|
|
|
2014-04-09 11:35:26 +00:00
|
|
|
def url_to_repo
|
2017-07-22 00:37:22 +00:00
|
|
|
gitlab_shell.url_to_repo(full_path)
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def ssh_url_to_repo
|
|
|
|
url_to_repo
|
|
|
|
end
|
|
|
|
|
2017-05-30 12:18:58 +00:00
|
|
|
def http_url_to_repo
|
2019-10-17 21:06:41 +00:00
|
|
|
@project.http_url_to_repo.sub(%r{git\z}, 'wiki.git')
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
2016-01-12 04:05:18 +00:00
|
|
|
def wiki_base_path
|
2019-12-05 18:07:51 +00:00
|
|
|
[Gitlab.config.gitlab.relative_url_root, '/', @project.full_path, '/-', '/wikis'].join('')
|
2016-01-12 04:05:18 +00:00
|
|
|
end
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
# Returns the Gitlab::Git::Wiki object.
|
2014-04-09 11:35:26 +00:00
|
|
|
def wiki
|
|
|
|
@wiki ||= begin
|
2019-03-18 16:51:11 +00:00
|
|
|
gl_repository = Gitlab::GlRepository::WIKI.identifier_for_subject(project)
|
2018-12-23 07:34:35 +00:00
|
|
|
raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository, full_path)
|
2017-10-03 16:58:33 +00:00
|
|
|
|
|
|
|
create_repo!(raw_repository) unless raw_repository.exists?
|
|
|
|
|
|
|
|
Gitlab::Git::Wiki.new(raw_repository)
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-13 01:56:40 +00:00
|
|
|
def repository_exists?
|
|
|
|
!!repository.exists?
|
|
|
|
end
|
2017-07-06 19:21:08 +00:00
|
|
|
|
|
|
|
def has_home_page?
|
|
|
|
!!find_page('home')
|
|
|
|
end
|
2016-08-13 01:56:40 +00:00
|
|
|
|
2018-07-12 06:19:20 +00:00
|
|
|
def empty?
|
2019-04-25 04:19:07 +00:00
|
|
|
list_pages(limit: 1).empty?
|
2018-07-12 06:19:20 +00:00
|
|
|
end
|
|
|
|
|
2019-08-01 05:54:52 +00:00
|
|
|
def exists?
|
|
|
|
!empty?
|
|
|
|
end
|
|
|
|
|
2019-04-25 04:19:07 +00:00
|
|
|
# Lists wiki pages of the repository.
|
|
|
|
#
|
|
|
|
# limit - max number of pages returned by the method.
|
|
|
|
# sort - criterion by which the pages are sorted.
|
|
|
|
# direction - order of the sorted pages.
|
|
|
|
# load_content - option, which specifies whether the content inside the page
|
|
|
|
# will be loaded.
|
|
|
|
#
|
2018-09-21 12:05:37 +00:00
|
|
|
# Returns an Array of GitLab WikiPage instances or an
|
2014-04-09 11:35:26 +00:00
|
|
|
# empty Array if this Wiki has no pages.
|
2019-04-25 04:19:07 +00:00
|
|
|
def list_pages(limit: 0, sort: nil, direction: DIRECTION_ASC, load_content: false)
|
|
|
|
wiki.list_pages(
|
|
|
|
limit: limit,
|
|
|
|
sort: sort,
|
|
|
|
direction_desc: direction == DIRECTION_DESC,
|
|
|
|
load_content: load_content
|
2019-04-04 16:28:56 +00:00
|
|
|
).map do |page|
|
|
|
|
WikiPage.new(self, page, true)
|
|
|
|
end
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Finds a page within the repository based on a tile
|
|
|
|
# or slug.
|
|
|
|
#
|
|
|
|
# title - The human readable or parameterized title of
|
|
|
|
# the page.
|
|
|
|
#
|
|
|
|
# Returns an initialized WikiPage instance or nil
|
|
|
|
def find_page(title, version = nil)
|
2014-04-28 14:22:31 +00:00
|
|
|
page_title, page_dir = page_title_and_dir(title)
|
2017-10-03 16:58:33 +00:00
|
|
|
|
|
|
|
if page = wiki.page(title: page_title, version: version, dir: page_dir)
|
2014-04-09 11:35:26 +00:00
|
|
|
WikiPage.new(self, page, true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-26 09:16:01 +00:00
|
|
|
def find_sidebar(version = nil)
|
|
|
|
find_page(SIDEBAR, version)
|
|
|
|
end
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
def find_file(name, version = nil)
|
|
|
|
wiki.file(name, version)
|
2014-03-28 20:15:25 +00:00
|
|
|
end
|
|
|
|
|
2014-04-09 11:35:26 +00:00
|
|
|
def create_page(title, content, format = :markdown, message = nil)
|
|
|
|
commit = commit_details(:created, message, title)
|
|
|
|
|
2016-02-28 12:11:43 +00:00
|
|
|
wiki.write_page(title, format.to_sym, content, commit)
|
2015-11-15 19:32:28 +00:00
|
|
|
|
|
|
|
update_project_activity
|
2017-10-03 16:58:33 +00:00
|
|
|
rescue Gitlab::Git::Wiki::DuplicatePageError => e
|
2014-04-09 11:35:26 +00:00
|
|
|
@error_message = "Duplicate page: #{e.message}"
|
2018-07-02 10:43:06 +00:00
|
|
|
false
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
2017-07-23 08:19:10 +00:00
|
|
|
def update_page(page, content:, title: nil, format: :markdown, message: nil)
|
2014-04-09 11:35:26 +00:00
|
|
|
commit = commit_details(:updated, message, page.title)
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
wiki.update_page(page.path, title || page.name, format.to_sym, content, commit)
|
2015-11-15 19:32:28 +00:00
|
|
|
|
|
|
|
update_project_activity
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def delete_page(page, message = nil)
|
2018-02-05 17:17:21 +00:00
|
|
|
return unless page
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
|
2015-11-15 19:32:28 +00:00
|
|
|
|
|
|
|
update_project_activity
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
2014-04-28 14:22:31 +00:00
|
|
|
def page_title_and_dir(title)
|
2018-02-05 17:17:21 +00:00
|
|
|
return unless title
|
|
|
|
|
2016-05-11 02:58:06 +00:00
|
|
|
title_array = title.split("/")
|
2014-04-28 14:22:31 +00:00
|
|
|
title = title_array.pop
|
2019-10-31 21:06:28 +00:00
|
|
|
[title, title_array.join("/")]
|
2014-04-28 14:22:31 +00:00
|
|
|
end
|
|
|
|
|
2014-09-25 10:56:23 +00:00
|
|
|
def repository
|
2019-03-18 16:51:11 +00:00
|
|
|
@repository ||= Repository.new(full_path, @project, disk_path: disk_path, repo_type: Gitlab::GlRepository::WIKI)
|
2014-09-25 10:56:23 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def default_branch
|
|
|
|
wiki.class.default_ref
|
|
|
|
end
|
|
|
|
|
2017-06-28 13:42:59 +00:00
|
|
|
def ensure_repository
|
2017-10-03 16:58:33 +00:00
|
|
|
raise CouldNotCreateWikiError unless wiki.repository_exists?
|
2017-06-28 13:42:59 +00:00
|
|
|
end
|
|
|
|
|
2016-05-13 07:21:01 +00:00
|
|
|
def hook_attrs
|
|
|
|
{
|
|
|
|
web_url: web_url,
|
|
|
|
git_ssh_url: ssh_url_to_repo,
|
|
|
|
git_http_url: http_url_to_repo,
|
2017-07-22 00:37:22 +00:00
|
|
|
path_with_namespace: full_path,
|
2016-05-27 23:31:03 +00:00
|
|
|
default_branch: default_branch
|
2016-05-13 07:21:01 +00:00
|
|
|
}
|
|
|
|
end
|
2014-04-09 11:35:26 +00:00
|
|
|
|
2016-03-18 14:31:19 +00:00
|
|
|
private
|
|
|
|
|
2017-10-03 16:58:33 +00:00
|
|
|
def create_repo!(raw_repository)
|
2019-01-17 21:50:18 +00:00
|
|
|
gitlab_shell.create_wiki_repository(project)
|
2017-10-03 16:58:33 +00:00
|
|
|
|
|
|
|
raise CouldNotCreateWikiError unless raw_repository.exists?
|
|
|
|
|
|
|
|
repository.after_create
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def commit_details(action, message = nil, title = nil)
|
2019-03-17 04:30:30 +00:00
|
|
|
commit_message = message.presence || default_message(action, title)
|
2018-09-18 09:04:15 +00:00
|
|
|
git_user = Gitlab::Git::User.from_gitlab(@user)
|
2014-04-09 11:35:26 +00:00
|
|
|
|
2018-04-18 17:50:56 +00:00
|
|
|
Gitlab::Git::Wiki::CommitDetails.new(@user.id,
|
2018-09-18 09:04:15 +00:00
|
|
|
git_user.username,
|
|
|
|
git_user.name,
|
|
|
|
git_user.email,
|
2018-04-18 17:50:56 +00:00
|
|
|
commit_message)
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def default_message(action, title)
|
|
|
|
"#{@user.username} #{action} page: #{title}"
|
|
|
|
end
|
|
|
|
|
2015-11-15 19:32:28 +00:00
|
|
|
def update_project_activity
|
2017-05-04 01:47:10 +00:00
|
|
|
@project.touch(:last_activity_at, :last_repository_updated_at)
|
2015-11-15 19:32:28 +00:00
|
|
|
end
|
2014-04-09 11:35:26 +00:00
|
|
|
end
|
2019-09-13 13:26:31 +00:00
|
|
|
|
|
|
|
ProjectWiki.prepend_if_ee('EE::ProjectWiki')
|