Allow moving wiki pages from the UI
This commit is contained in:
parent
0a30a9ea59
commit
27c08a1689
19 changed files with 567 additions and 41 deletions
4
Gemfile
4
Gemfile
|
@ -69,6 +69,10 @@ gem 'net-ldap'
|
|||
|
||||
# Git Wiki
|
||||
# Required manually in config/initializers/gollum.rb to control load order
|
||||
# Before updating this gem, check if
|
||||
# https://github.com/gollum/gollum-lib/pull/292 has been merged.
|
||||
# If it has, then remove the monkey patch for update_page, rename_page and raw_data_in_committer
|
||||
# in config/initializers/gollum.rb
|
||||
gem 'gollum-lib', '~> 4.2', require: false
|
||||
|
||||
# Before updating this gem, check if
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
.wiki-form {
|
||||
.edit-wiki-page-slug-tip {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.title .edit-wiki-header {
|
||||
width: 780px;
|
||||
margin-left: auto;
|
||||
|
|
|
@ -54,8 +54,8 @@ class Projects::WikisController < Projects::ApplicationController
|
|||
else
|
||||
render 'edit'
|
||||
end
|
||||
rescue WikiPage::PageChangedError
|
||||
@conflict = true
|
||||
rescue WikiPage::PageChangedError, WikiPage::PageRenameError => e
|
||||
@error = e
|
||||
render 'edit'
|
||||
end
|
||||
|
||||
|
|
|
@ -21,4 +21,22 @@ module WikiHelper
|
|||
add_to_breadcrumb_dropdown link_to(WikiPage.unhyphenize(dir_or_page).capitalize, project_wiki_path(@project, current_slug)), location: :after
|
||||
end
|
||||
end
|
||||
|
||||
def wiki_page_errors(error)
|
||||
return unless error
|
||||
|
||||
content_tag(:div, class: 'alert alert-danger') do
|
||||
case error
|
||||
when WikiPage::PageChangedError
|
||||
page_link = link_to s_("WikiPageConflictMessage|the page"), project_wiki_path(@project, @page), target: "_blank"
|
||||
concat(
|
||||
(s_("WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs.") % { page_link: page_link }).html_safe
|
||||
)
|
||||
when WikiPage::PageRenameError
|
||||
s_("WikiEdit|There is already a page with the same title in that path.")
|
||||
else
|
||||
error.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -119,6 +119,8 @@ class ProjectWiki
|
|||
end
|
||||
|
||||
def delete_page(page, message = nil)
|
||||
return unless page
|
||||
|
||||
wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
|
||||
|
||||
update_project_activity
|
||||
|
@ -131,6 +133,8 @@ class ProjectWiki
|
|||
end
|
||||
|
||||
def page_title_and_dir(title)
|
||||
return unless title
|
||||
|
||||
title_array = title.split("/")
|
||||
title = title_array.pop
|
||||
[title, title_array.join("/")]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class WikiPage
|
||||
PageChangedError = Class.new(StandardError)
|
||||
PageRenameError = Class.new(StandardError)
|
||||
|
||||
include ActiveModel::Validations
|
||||
include ActiveModel::Conversion
|
||||
|
@ -102,7 +103,7 @@ class WikiPage
|
|||
|
||||
# The hierarchy of the directory this page is contained in.
|
||||
def directory
|
||||
wiki.page_title_and_dir(slug).last
|
||||
wiki.page_title_and_dir(slug)&.last.to_s
|
||||
end
|
||||
|
||||
# The processed/formatted content of this page.
|
||||
|
@ -177,7 +178,7 @@ class WikiPage
|
|||
# Creates a new Wiki Page.
|
||||
#
|
||||
# attr - Hash of attributes to set on the new page.
|
||||
# :title - The title for the new page.
|
||||
# :title - The title (optionally including dir) for the new page.
|
||||
# :content - The raw markup content.
|
||||
# :format - Optional symbol representing the
|
||||
# content format. Can be any type
|
||||
|
@ -189,7 +190,7 @@ class WikiPage
|
|||
# Returns the String SHA1 of the newly created page
|
||||
# or False if the save was unsuccessful.
|
||||
def create(attrs = {})
|
||||
@attributes.merge!(attrs)
|
||||
update_attributes(attrs)
|
||||
|
||||
save(page_details: title) do
|
||||
wiki.create_page(title, content, format, message)
|
||||
|
@ -204,24 +205,29 @@ class WikiPage
|
|||
# See ProjectWiki::MARKUPS Hash for available formats.
|
||||
# :message - Optional commit message to set on the new version.
|
||||
# :last_commit_sha - Optional last commit sha to validate the page unchanged.
|
||||
# :title - The Title to replace existing title
|
||||
# :title - The Title (optionally including dir) to replace existing title
|
||||
#
|
||||
# Returns the String SHA1 of the newly created page
|
||||
# or False if the save was unsuccessful.
|
||||
def update(attrs = {})
|
||||
last_commit_sha = attrs.delete(:last_commit_sha)
|
||||
|
||||
if last_commit_sha && last_commit_sha != self.last_commit_sha
|
||||
raise PageChangedError.new("You are attempting to update a page that has changed since you started editing it.")
|
||||
raise PageChangedError
|
||||
end
|
||||
|
||||
attrs.slice!(:content, :format, :message, :title)
|
||||
@attributes.merge!(attrs)
|
||||
page_details =
|
||||
if title.present? && @page.title != title
|
||||
title
|
||||
else
|
||||
@page.url_path
|
||||
update_attributes(attrs)
|
||||
|
||||
if title_changed?
|
||||
page_details = title
|
||||
|
||||
if wiki.find_page(page_details).present?
|
||||
@attributes[:title] = @page.url_path
|
||||
raise PageRenameError
|
||||
end
|
||||
else
|
||||
page_details = @page.url_path
|
||||
end
|
||||
|
||||
save(page_details: page_details) do
|
||||
wiki.update_page(
|
||||
|
@ -255,8 +261,44 @@ class WikiPage
|
|||
page.version.to_s
|
||||
end
|
||||
|
||||
def title_changed?
|
||||
title.present? && self.class.unhyphenize(@page.url_path) != title
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Process and format the title based on the user input.
|
||||
def process_title(title)
|
||||
return if title.blank?
|
||||
|
||||
title = deep_title_squish(title)
|
||||
current_dirname = File.dirname(title)
|
||||
|
||||
if @page.present?
|
||||
return title[1..-1] if current_dirname == '/'
|
||||
return File.join([directory.presence, title].compact) if current_dirname == '.'
|
||||
end
|
||||
|
||||
title
|
||||
end
|
||||
|
||||
# This method squishes all the filename
|
||||
# i.e: ' foo / bar / page_name' => 'foo/bar/page_name'
|
||||
def deep_title_squish(title)
|
||||
components = title.split(File::SEPARATOR).map(&:squish)
|
||||
|
||||
File.join(components)
|
||||
end
|
||||
|
||||
# Updates the current @attributes hash by merging a hash of params
|
||||
def update_attributes(attrs)
|
||||
attrs[:title] = process_title(attrs[:title]) if attrs[:title].present?
|
||||
|
||||
attrs.slice!(:content, :format, :message, :title)
|
||||
|
||||
@attributes.merge!(attrs)
|
||||
end
|
||||
|
||||
def set_attributes
|
||||
attributes[:slug] = @page.url_path
|
||||
attributes[:title] = @page.title
|
||||
|
|
|
@ -9,7 +9,13 @@
|
|||
|
||||
.form-group
|
||||
.col-sm-12= f.label :title, class: 'control-label-full-width'
|
||||
.col-sm-12= f.text_field :title, class: 'form-control', value: @page.title
|
||||
.col-sm-12
|
||||
= f.text_field :title, class: 'form-control', value: @page.title
|
||||
- if @page.persisted?
|
||||
%span.edit-wiki-page-slug-tip
|
||||
= icon('lightbulb-o')
|
||||
= s_("WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title.")
|
||||
= link_to icon('question-circle'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'), target: '_blank'
|
||||
.form-group
|
||||
.col-sm-12= f.label :format, class: 'control-label-full-width'
|
||||
.col-sm-12
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
- @content_class = "limit-container-width limit-container-width-sm" unless fluid_layout
|
||||
- page_title _("Edit"), @page.title.capitalize, _("Wiki")
|
||||
|
||||
- if @conflict
|
||||
.alert.alert-danger
|
||||
- page_link = link_to s_("WikiPageConflictMessage|the page"), project_wiki_path(@project, @page), target: "_blank"
|
||||
= (s_("WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs.") % { page_link: page_link }).html_safe
|
||||
= wiki_page_errors(@error)
|
||||
|
||||
.wiki-page-header.has-sidebar-toggle
|
||||
%button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" }
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Allow moving wiki pages from the UI
|
||||
merge_request: 16313
|
||||
author:
|
||||
type: fixed
|
|
@ -35,6 +35,88 @@ module Gollum
|
|||
[]
|
||||
end
|
||||
end
|
||||
|
||||
# Remove if https://github.com/gollum/gollum-lib/pull/292 has been merged
|
||||
def update_page(page, name, format, data, commit = {})
|
||||
name = name ? ::File.basename(name) : page.name
|
||||
format ||= page.format
|
||||
dir = ::File.dirname(page.path)
|
||||
dir = '' if dir == '.'
|
||||
filename = (rename = page.name != name) ? Gollum::Page.cname(name) : page.filename_stripped
|
||||
|
||||
multi_commit = !!commit[:committer]
|
||||
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
|
||||
|
||||
if !rename && page.format == format
|
||||
committer.add(page.path, normalize(data))
|
||||
else
|
||||
committer.delete(page.path)
|
||||
committer.add_to_index(dir, filename, format, data)
|
||||
end
|
||||
|
||||
committer.after_commit do |index, _sha|
|
||||
@access.refresh
|
||||
index.update_working_dir(dir, page.filename_stripped, page.format)
|
||||
index.update_working_dir(dir, filename, format)
|
||||
end
|
||||
|
||||
multi_commit ? committer : committer.commit
|
||||
end
|
||||
|
||||
# Remove if https://github.com/gollum/gollum-lib/pull/292 has been merged
|
||||
def rename_page(page, rename, commit = {})
|
||||
return false if page.nil?
|
||||
return false if rename.nil? || rename.empty?
|
||||
|
||||
(target_dir, target_name) = ::File.split(rename)
|
||||
(source_dir, source_name) = ::File.split(page.path)
|
||||
source_name = page.filename_stripped
|
||||
|
||||
# File.split gives us relative paths with ".", commiter.add_to_index doesn't like that.
|
||||
target_dir = '' if target_dir == '.'
|
||||
source_dir = '' if source_dir == '.'
|
||||
target_dir = target_dir.gsub(/^\//, '') # rubocop:disable Style/RegexpLiteral
|
||||
|
||||
# if the rename is a NOOP, abort
|
||||
if source_dir == target_dir && source_name == target_name
|
||||
return false
|
||||
end
|
||||
|
||||
multi_commit = !!commit[:committer]
|
||||
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
|
||||
|
||||
# This piece only works for multi_commit
|
||||
# If we are in a commit batch and one of the previous operations
|
||||
# has updated the page, any information we ask to the page can be outdated.
|
||||
# Therefore, we should ask first to the current committer tree to see if
|
||||
# there is any updated change.
|
||||
raw_data = raw_data_in_committer(committer, source_dir, page.filename) ||
|
||||
raw_data_in_committer(committer, source_dir, "#{target_name}.#{Page.format_to_ext(page.format)}") ||
|
||||
page.raw_data
|
||||
|
||||
committer.delete(page.path)
|
||||
committer.add_to_index(target_dir, target_name, page.format, raw_data)
|
||||
|
||||
committer.after_commit do |index, _sha|
|
||||
@access.refresh
|
||||
index.update_working_dir(source_dir, source_name, page.format)
|
||||
index.update_working_dir(target_dir, target_name, page.format)
|
||||
end
|
||||
|
||||
multi_commit ? committer : committer.commit
|
||||
end
|
||||
|
||||
# Remove if https://github.com/gollum/gollum-lib/pull/292 has been merged
|
||||
def raw_data_in_committer(committer, dir, filename)
|
||||
data = nil
|
||||
|
||||
[*dir.split(::File::SEPARATOR), filename].each do |key|
|
||||
data = data ? data[key] : committer.tree[key]
|
||||
break unless data
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
module Git
|
||||
|
|
BIN
doc/user/project/wiki/img/wiki_move_page_1.png
Normal file
BIN
doc/user/project/wiki/img/wiki_move_page_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
BIN
doc/user/project/wiki/img/wiki_move_page_2.png
Normal file
BIN
doc/user/project/wiki/img/wiki_move_page_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
|
@ -64,6 +64,18 @@ effect.
|
|||
You can find the **Delete** button only when editing a page. Click on it and
|
||||
confirm you want the page to be deleted.
|
||||
|
||||
## Moving a wiki page
|
||||
|
||||
You can move a wiki page from one directory to another by specifying the full
|
||||
path in the wiki page title in the [edit](#editing-a-wiki-page) form.
|
||||
|
||||
![Moving a page](img/wiki_move_page_1.png)
|
||||
|
||||
![After moving a page](img/wiki_move_page_2.png)
|
||||
|
||||
In order to move a wiki page to the root directory, the wiki page title must
|
||||
be preceded by the slash (`/`) character.
|
||||
|
||||
## Viewing a list of all created wiki pages
|
||||
|
||||
Every wiki has a sidebar from which a short list of the created pages can be
|
||||
|
|
|
@ -25,8 +25,9 @@ module Gitlab
|
|||
@repository.exists?
|
||||
end
|
||||
|
||||
# Disabled because of https://gitlab.com/gitlab-org/gitaly/merge_requests/539
|
||||
def write_page(name, format, content, commit_details)
|
||||
@repository.gitaly_migrate(:wiki_write_page) do |is_enabled|
|
||||
@repository.gitaly_migrate(:wiki_write_page, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_write_page(name, format, content, commit_details)
|
||||
gollum_wiki.clear_cache
|
||||
|
@ -47,8 +48,9 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
# Disable because of https://gitlab.com/gitlab-org/gitlab-ce/issues/42094
|
||||
def update_page(page_path, title, format, content, commit_details)
|
||||
@repository.gitaly_migrate(:wiki_update_page) do |is_enabled|
|
||||
@repository.gitaly_migrate(:wiki_update_page, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_update_page(page_path, title, format, content, commit_details)
|
||||
gollum_wiki.clear_cache
|
||||
|
@ -68,8 +70,9 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
# Disable because of https://gitlab.com/gitlab-org/gitlab-ce/issues/42039
|
||||
def page(title:, version: nil, dir: nil)
|
||||
@repository.gitaly_migrate(:wiki_find_page) do |is_enabled|
|
||||
@repository.gitaly_migrate(:wiki_find_page, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_find_page(title: title, version: version, dir: dir)
|
||||
else
|
||||
|
@ -192,7 +195,10 @@ module Gitlab
|
|||
assert_type!(format, Symbol)
|
||||
assert_type!(commit_details, CommitDetails)
|
||||
|
||||
gollum_wiki.write_page(name, format, content, commit_details.to_h)
|
||||
filename = File.basename(name)
|
||||
dir = (tmp_dir = File.dirname(name)) == '.' ? '' : tmp_dir
|
||||
|
||||
gollum_wiki.write_page(filename, format, content, commit_details.to_h, dir)
|
||||
|
||||
nil
|
||||
rescue Gollum::DuplicatePageError => e
|
||||
|
@ -210,7 +216,15 @@ module Gitlab
|
|||
assert_type!(format, Symbol)
|
||||
assert_type!(commit_details, CommitDetails)
|
||||
|
||||
gollum_wiki.update_page(gollum_page_by_path(page_path), title, format, content, commit_details.to_h)
|
||||
page = gollum_page_by_path(page_path)
|
||||
committer = Gollum::Committer.new(page.wiki, commit_details.to_h)
|
||||
|
||||
# Instead of performing two renames if the title has changed,
|
||||
# the update_page will only update the format and content and
|
||||
# the rename_page will do anything related to moving/renaming
|
||||
gollum_wiki.update_page(page, page.name, format, content, committer: committer)
|
||||
gollum_wiki.rename_page(page, title, committer: committer)
|
||||
committer.commit
|
||||
nil
|
||||
end
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: gitlab 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-01-30 14:59+0100\n"
|
||||
"PO-Revision-Date: 2018-01-30 14:59+0100\n"
|
||||
"POT-Creation-Date: 2018-02-05 16:03+0100\n"
|
||||
"PO-Revision-Date: 2018-02-05 16:03+0100\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
|
@ -23,6 +23,11 @@ msgid_plural "%d commits"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d commit behind"
|
||||
msgid_plural "%d commits behind"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d issue"
|
||||
msgid_plural "%d issues"
|
||||
msgstr[0] ""
|
||||
|
@ -157,6 +162,18 @@ msgstr ""
|
|||
msgid "An error occurred while fetching sidebar data"
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while getting projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while loading filenames"
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while rendering KaTeX"
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while retrieving calendar activity"
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while retrieving diff"
|
||||
msgstr ""
|
||||
|
||||
|
@ -480,6 +497,24 @@ msgstr ""
|
|||
msgid "CiStatus|running"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiVariables|Input variable key"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiVariables|Input variable value"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiVariables|Remove variable row"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiVariable|All environments"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiVariable|Protected"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiVariable|Toggle protected"
|
||||
msgstr ""
|
||||
|
||||
msgid "CircuitBreakerApiLink|circuitbreaker api"
|
||||
msgstr ""
|
||||
|
||||
|
@ -791,6 +826,9 @@ msgstr ""
|
|||
msgid "Commits|An error occurred while fetching merge requests data."
|
||||
msgstr ""
|
||||
|
||||
msgid "Commits|Commit: %{commitText}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Commits|History"
|
||||
msgstr ""
|
||||
|
||||
|
@ -890,6 +928,9 @@ msgstr ""
|
|||
msgid "Copy URL to clipboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy branch name to clipboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy commit SHA to clipboard"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1099,12 +1140,33 @@ msgstr ""
|
|||
msgid "Environments|You don't have any environments right now."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching contributors data."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching labels."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching network graph."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching refs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching usage ping data."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error occurred when toggling the notification subscription"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error saving label update."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error updating status for all todos."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error updating todo status."
|
||||
msgstr ""
|
||||
|
||||
msgid "EventFilterBy|Filter by all"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1716,12 +1778,6 @@ msgstr ""
|
|||
msgid "PipelineSchedules|Inactive"
|
||||
msgstr ""
|
||||
|
||||
msgid "PipelineSchedules|Input variable key"
|
||||
msgstr ""
|
||||
|
||||
msgid "PipelineSchedules|Input variable value"
|
||||
msgstr ""
|
||||
|
||||
msgid "PipelineSchedules|Next Run"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1731,9 +1787,6 @@ msgstr ""
|
|||
msgid "PipelineSchedules|Provide a short description for this pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "PipelineSchedules|Remove variable row"
|
||||
msgstr ""
|
||||
|
||||
msgid "PipelineSchedules|Take ownership"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2116,6 +2169,9 @@ msgstr[1] ""
|
|||
msgid "Snippets"
|
||||
msgstr ""
|
||||
|
||||
msgid "Something went wrong on our end"
|
||||
msgstr ""
|
||||
|
||||
msgid "Something went wrong on our end."
|
||||
msgstr ""
|
||||
|
||||
|
@ -2424,6 +2480,18 @@ msgstr ""
|
|||
msgid "There are problems accessing Git storage: "
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error saving your notification settings."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error when reseting email token."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error when subscribing to this label."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error when unsubscribing from this label."
|
||||
msgstr ""
|
||||
|
||||
msgid "This directory"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2635,6 +2703,9 @@ msgstr ""
|
|||
msgid "Trigger this manual action"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type %{value} to confirm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unable to reset project cache."
|
||||
msgstr ""
|
||||
|
||||
|
@ -2719,6 +2790,12 @@ msgstr ""
|
|||
msgid "WikiClone|Start Gollum and edit locally"
|
||||
msgstr ""
|
||||
|
||||
msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
|
||||
msgstr ""
|
||||
|
||||
msgid "WikiEdit|There is already a page with the same title in that path."
|
||||
msgstr ""
|
||||
|
||||
msgid "WikiEmptyPageError|You are not allowed to create wiki pages"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2897,6 +2974,9 @@ msgstr[1] ""
|
|||
msgid "mrWidget|Cancel automatic merge"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Check out branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Checking ability to merge automatically"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2906,9 +2986,27 @@ msgstr ""
|
|||
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Closed"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Closed by"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Closes"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Did not close"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Email patches"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Mentions"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Merge"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2921,6 +3019,9 @@ msgstr ""
|
|||
msgid "mrWidget|Merged by"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Plain diff"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Refresh"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2936,6 +3037,9 @@ msgstr ""
|
|||
msgid "mrWidget|Remove source branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Request to merge"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Resolve conflicts"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2981,9 +3085,18 @@ msgstr ""
|
|||
msgid "mrWidget|This project is archived, write access has been disabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|You can merge this merge request manually using the"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|You can remove source branch now"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|command line"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|into"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User updates wiki page' do
|
||||
# Remove skip_gitaly_mock flag when gitaly_update_page implements moving pages
|
||||
describe 'User updates wiki page', :skip_gitaly_mock do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
|
@ -143,6 +144,7 @@ describe 'User updates wiki page' do
|
|||
expect(page).to have_field('wiki[message]', with: 'Update home')
|
||||
|
||||
fill_in(:wiki_content, with: 'My awesome wiki!')
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(page).to have_content('Home')
|
||||
|
@ -151,4 +153,74 @@ describe 'User updates wiki page' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the page is in a subdir' do
|
||||
let!(:project) { create(:project, namespace: user.namespace) }
|
||||
let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
|
||||
let(:page_name) { 'page_name' }
|
||||
let(:page_dir) { "foo/bar/#{page_name}" }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: page_dir, content: 'Home page' }) }
|
||||
|
||||
before do
|
||||
visit(project_wiki_edit_path(project, wiki_page))
|
||||
end
|
||||
|
||||
it 'moves the page to the root folder' do
|
||||
fill_in(:wiki_title, with: "/#{page_name}")
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(current_path).to eq(project_wiki_path(project, page_name))
|
||||
end
|
||||
|
||||
it 'moves the page to other dir' do
|
||||
new_page_dir = "foo1/bar1/#{page_name}"
|
||||
|
||||
fill_in(:wiki_title, with: new_page_dir)
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(current_path).to eq(project_wiki_path(project, new_page_dir))
|
||||
end
|
||||
|
||||
it 'remains in the same place if title has not changed' do
|
||||
original_path = project_wiki_path(project, wiki_page)
|
||||
|
||||
fill_in(:wiki_title, with: page_name)
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(current_path).to eq(original_path)
|
||||
end
|
||||
|
||||
it 'can be moved to a different dir with a different name' do
|
||||
new_page_dir = "foo1/bar1/new_page_name"
|
||||
|
||||
fill_in(:wiki_title, with: new_page_dir)
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(current_path).to eq(project_wiki_path(project, new_page_dir))
|
||||
end
|
||||
|
||||
it 'can be renamed and moved to the root folder' do
|
||||
new_name = 'new_page_name'
|
||||
|
||||
fill_in(:wiki_title, with: "/#{new_name}")
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(current_path).to eq(project_wiki_path(project, new_name))
|
||||
end
|
||||
|
||||
it 'squishes the title before creating the page' do
|
||||
new_page_dir = " foo1 / bar1 / #{page_name} "
|
||||
|
||||
fill_in(:wiki_title, with: new_page_dir)
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User views a wiki page' do
|
||||
# Remove skip_gitaly_mock flag when gitaly_update_page implements moving pages
|
||||
describe 'User views a wiki page', :skip_gitaly_mock do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, namespace: user.namespace) }
|
||||
let(:wiki_page) do
|
||||
|
|
36
spec/lib/gitlab/git/wiki_spec.rb
Normal file
36
spec/lib/gitlab/git/wiki_spec.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Git::Wiki do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { project.owner }
|
||||
let(:wiki) { ProjectWiki.new(project, user) }
|
||||
let(:gollum_wiki) { wiki.wiki }
|
||||
|
||||
# Remove skip_gitaly_mock flag when gitaly_find_page when
|
||||
# https://gitlab.com/gitlab-org/gitaly/merge_requests/539 gets merged
|
||||
describe '#page', :skip_gitaly_mock do
|
||||
it 'returns the right page' do
|
||||
create_page('page1', 'content')
|
||||
create_page('foo/page1', 'content')
|
||||
|
||||
expect(gollum_wiki.page(title: 'page1', dir: '').url_path).to eq 'page1'
|
||||
expect(gollum_wiki.page(title: 'page1', dir: 'foo').url_path).to eq 'foo/page1'
|
||||
|
||||
destroy_page('page1')
|
||||
destroy_page('page1', 'foo')
|
||||
end
|
||||
end
|
||||
|
||||
def create_page(name, content)
|
||||
gollum_wiki.write_page(name, :markdown, content, commit_details)
|
||||
end
|
||||
|
||||
def commit_details
|
||||
Gitlab::Git::Wiki::CommitDetails.new(user.name, user.email, "test commit")
|
||||
end
|
||||
|
||||
def destroy_page(title, dir = '')
|
||||
page = gollum_wiki.page(title: title, dir: dir)
|
||||
wiki.delete_page(page, "test commit")
|
||||
end
|
||||
end
|
|
@ -188,14 +188,37 @@ describe WikiPage do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
describe '#create', :skip_gitaly_mock do
|
||||
context 'with valid attributes' do
|
||||
it 'raises an error if a page with the same path already exists' do
|
||||
create_page('New Page', 'content')
|
||||
create_page('foo/bar', 'content')
|
||||
expect { create_page('New Page', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
|
||||
expect { create_page('foo/bar', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
|
||||
|
||||
destroy_page('New Page')
|
||||
destroy_page('bar', 'foo')
|
||||
end
|
||||
|
||||
it 'if the title is preceded by a / it is removed' do
|
||||
create_page('/New Page', 'content')
|
||||
|
||||
expect(wiki.find_page('New Page')).not_to be_nil
|
||||
|
||||
destroy_page('New Page')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove skip_gitaly_mock flag when gitaly_update_page implements moving pages
|
||||
describe "#update", :skip_gitaly_mock do
|
||||
before do
|
||||
create_page("Update", "content")
|
||||
@page = wiki.find_page("Update")
|
||||
end
|
||||
|
||||
after do
|
||||
destroy_page(@page.title)
|
||||
destroy_page(@page.title, @page.directory)
|
||||
end
|
||||
|
||||
context "with valid attributes" do
|
||||
|
@ -233,6 +256,95 @@ describe WikiPage do
|
|||
expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when renaming a page' do
|
||||
it 'raises an error if the page already exists' do
|
||||
create_page('Existing Page', 'content')
|
||||
|
||||
expect { @page.update(title: 'Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
|
||||
expect(@page.title).to eq 'Update'
|
||||
expect(@page.content).to eq 'new_content'
|
||||
|
||||
destroy_page('Existing Page')
|
||||
end
|
||||
|
||||
it 'updates the content and rename the file' do
|
||||
new_title = 'Renamed Page'
|
||||
new_content = 'updated content'
|
||||
|
||||
expect(@page.update(title: new_title, content: new_content)).to be_truthy
|
||||
|
||||
@page = wiki.find_page(new_title)
|
||||
|
||||
expect(@page).not_to be_nil
|
||||
expect(@page.content).to eq new_content
|
||||
end
|
||||
end
|
||||
|
||||
context 'when moving a page' do
|
||||
it 'raises an error if the page already exists' do
|
||||
create_page('foo/Existing Page', 'content')
|
||||
|
||||
expect { @page.update(title: 'foo/Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
|
||||
expect(@page.title).to eq 'Update'
|
||||
expect(@page.content).to eq 'new_content'
|
||||
|
||||
destroy_page('Existing Page', 'foo')
|
||||
end
|
||||
|
||||
it 'updates the content and moves the file' do
|
||||
new_title = 'foo/Other Page'
|
||||
new_content = 'new_content'
|
||||
|
||||
expect(@page.update(title: new_title, content: new_content)).to be_truthy
|
||||
|
||||
page = wiki.find_page(new_title)
|
||||
|
||||
expect(page).not_to be_nil
|
||||
expect(page.content).to eq new_content
|
||||
end
|
||||
|
||||
context 'in subdir' do
|
||||
before do
|
||||
create_page('foo/Existing Page', 'content')
|
||||
@page = wiki.find_page('foo/Existing Page')
|
||||
end
|
||||
|
||||
it 'moves the page to the root folder if the title is preceded by /' do
|
||||
expect(@page.slug).to eq 'foo/Existing-Page'
|
||||
expect(@page.update(title: '/Existing Page', content: 'new_content')).to be_truthy
|
||||
expect(@page.slug).to eq 'Existing-Page'
|
||||
end
|
||||
|
||||
it 'does nothing if it has the same title' do
|
||||
original_path = @page.slug
|
||||
|
||||
expect(@page.update(title: 'Existing Page', content: 'new_content')).to be_truthy
|
||||
expect(@page.slug).to eq original_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'in root dir' do
|
||||
it 'does nothing if the title is preceded by /' do
|
||||
original_path = @page.slug
|
||||
|
||||
expect(@page.update(title: '/Update', content: 'new_content')).to be_truthy
|
||||
expect(@page.slug).to eq original_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid attributes" do
|
||||
it 'aborts update if title blank' do
|
||||
expect(@page.update(title: '', content: 'new_content')).to be_falsey
|
||||
expect(@page.content).to eq 'new_content'
|
||||
|
||||
page = wiki.find_page('Update')
|
||||
expect(page.content).to eq 'content'
|
||||
|
||||
@page.title = 'Update'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#destroy" do
|
||||
|
@ -421,8 +533,8 @@ describe WikiPage do
|
|||
wiki.wiki.write_page(name, :markdown, content, commit_details)
|
||||
end
|
||||
|
||||
def destroy_page(title)
|
||||
page = wiki.wiki.page(title: title)
|
||||
def destroy_page(title, dir = '')
|
||||
page = wiki.wiki.page(title: title, dir: dir)
|
||||
wiki.delete_page(page, "test commit")
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue