Commit 1214d8de authored by Sean McGivern's avatar Sean McGivern

Merge branch 'fj-37273-moving-wiki-pages-from-the-ui' into 'master'

Allow moving wiki pages from the UI

Closes #37273

See merge request gitlab-org/gitlab-ce!16313
parents 0a30a9ea 27c08a16
...@@ -69,6 +69,10 @@ gem 'net-ldap' ...@@ -69,6 +69,10 @@ gem 'net-ldap'
# Git Wiki # Git Wiki
# Required manually in config/initializers/gollum.rb to control load order # 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 gem 'gollum-lib', '~> 4.2', require: false
# Before updating this gem, check if # Before updating this gem, check if
......
...@@ -6,6 +6,14 @@ ...@@ -6,6 +6,14 @@
} }
} }
.wiki-form {
.edit-wiki-page-slug-tip {
display: inline-block;
max-width: 100%;
margin-top: 5px;
}
}
.title .edit-wiki-header { .title .edit-wiki-header {
width: 780px; width: 780px;
margin-left: auto; margin-left: auto;
......
...@@ -54,8 +54,8 @@ class Projects::WikisController < Projects::ApplicationController ...@@ -54,8 +54,8 @@ class Projects::WikisController < Projects::ApplicationController
else else
render 'edit' render 'edit'
end end
rescue WikiPage::PageChangedError rescue WikiPage::PageChangedError, WikiPage::PageRenameError => e
@conflict = true @error = e
render 'edit' render 'edit'
end end
......
...@@ -21,4 +21,22 @@ module WikiHelper ...@@ -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 add_to_breadcrumb_dropdown link_to(WikiPage.unhyphenize(dir_or_page).capitalize, project_wiki_path(@project, current_slug)), location: :after
end end
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 end
...@@ -119,6 +119,8 @@ class ProjectWiki ...@@ -119,6 +119,8 @@ class ProjectWiki
end end
def delete_page(page, message = nil) def delete_page(page, message = nil)
return unless page
wiki.delete_page(page.path, commit_details(:deleted, message, page.title)) wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
update_project_activity update_project_activity
...@@ -131,6 +133,8 @@ class ProjectWiki ...@@ -131,6 +133,8 @@ class ProjectWiki
end end
def page_title_and_dir(title) def page_title_and_dir(title)
return unless title
title_array = title.split("/") title_array = title.split("/")
title = title_array.pop title = title_array.pop
[title, title_array.join("/")] [title, title_array.join("/")]
......
class WikiPage class WikiPage
PageChangedError = Class.new(StandardError) PageChangedError = Class.new(StandardError)
PageRenameError = Class.new(StandardError)
include ActiveModel::Validations include ActiveModel::Validations
include ActiveModel::Conversion include ActiveModel::Conversion
...@@ -102,7 +103,7 @@ class WikiPage ...@@ -102,7 +103,7 @@ class WikiPage
# The hierarchy of the directory this page is contained in. # The hierarchy of the directory this page is contained in.
def directory def directory
wiki.page_title_and_dir(slug).last wiki.page_title_and_dir(slug)&.last.to_s
end end
# The processed/formatted content of this page. # The processed/formatted content of this page.
...@@ -177,7 +178,7 @@ class WikiPage ...@@ -177,7 +178,7 @@ class WikiPage
# Creates a new Wiki Page. # Creates a new Wiki Page.
# #
# attr - Hash of attributes to set on the new 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. # :content - The raw markup content.
# :format - Optional symbol representing the # :format - Optional symbol representing the
# content format. Can be any type # content format. Can be any type
...@@ -189,7 +190,7 @@ class WikiPage ...@@ -189,7 +190,7 @@ class WikiPage
# Returns the String SHA1 of the newly created page # Returns the String SHA1 of the newly created page
# or False if the save was unsuccessful. # or False if the save was unsuccessful.
def create(attrs = {}) def create(attrs = {})
@attributes.merge!(attrs) update_attributes(attrs)
save(page_details: title) do save(page_details: title) do
wiki.create_page(title, content, format, message) wiki.create_page(title, content, format, message)
...@@ -204,23 +205,28 @@ class WikiPage ...@@ -204,23 +205,28 @@ class WikiPage
# See ProjectWiki::MARKUPS Hash for available formats. # See ProjectWiki::MARKUPS Hash for available formats.
# :message - Optional commit message to set on the new version. # :message - Optional commit message to set on the new version.
# :last_commit_sha - Optional last commit sha to validate the page unchanged. # :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 # Returns the String SHA1 of the newly created page
# or False if the save was unsuccessful. # or False if the save was unsuccessful.
def update(attrs = {}) def update(attrs = {})
last_commit_sha = attrs.delete(:last_commit_sha) last_commit_sha = attrs.delete(:last_commit_sha)
if last_commit_sha && last_commit_sha != self.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 end
attrs.slice!(:content, :format, :message, :title) update_attributes(attrs)
@attributes.merge!(attrs)
page_details = if title_changed?
if title.present? && @page.title != title page_details = title
title
if wiki.find_page(page_details).present?
@attributes[:title] = @page.url_path
raise PageRenameError
end
else else
@page.url_path page_details = @page.url_path
end end
save(page_details: page_details) do save(page_details: page_details) do
...@@ -255,8 +261,44 @@ class WikiPage ...@@ -255,8 +261,44 @@ class WikiPage
page.version.to_s page.version.to_s
end end
def title_changed?
title.present? && self.class.unhyphenize(@page.url_path) != title
end
private 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 def set_attributes
attributes[:slug] = @page.url_path attributes[:slug] = @page.url_path
attributes[:title] = @page.title attributes[:title] = @page.title
......
...@@ -9,7 +9,13 @@ ...@@ -9,7 +9,13 @@
.form-group .form-group
.col-sm-12= f.label :title, class: 'control-label-full-width' .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 .form-group
.col-sm-12= f.label :format, class: 'control-label-full-width' .col-sm-12= f.label :format, class: 'control-label-full-width'
.col-sm-12 .col-sm-12
......
- @content_class = "limit-container-width limit-container-width-sm" unless fluid_layout - @content_class = "limit-container-width limit-container-width-sm" unless fluid_layout
- page_title _("Edit"), @page.title.capitalize, _("Wiki") - page_title _("Edit"), @page.title.capitalize, _("Wiki")
- if @conflict = wiki_page_errors(@error)
.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-header.has-sidebar-toggle .wiki-page-header.has-sidebar-toggle
%button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" } %button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" }
......
---
title: Allow moving wiki pages from the UI
merge_request: 16313
author:
type: fixed
...@@ -35,6 +35,88 @@ module Gollum ...@@ -35,6 +35,88 @@ module Gollum
[] []
end end
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 end
module Git module Git
......
...@@ -64,6 +64,18 @@ effect. ...@@ -64,6 +64,18 @@ effect.
You can find the **Delete** button only when editing a page. Click on it and You can find the **Delete** button only when editing a page. Click on it and
confirm you want the page to be deleted. 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 ## Viewing a list of all created wiki pages
Every wiki has a sidebar from which a short list of the created pages can be Every wiki has a sidebar from which a short list of the created pages can be
......
...@@ -25,8 +25,9 @@ module Gitlab ...@@ -25,8 +25,9 @@ module Gitlab
@repository.exists? @repository.exists?
end end
# Disabled because of https://gitlab.com/gitlab-org/gitaly/merge_requests/539
def write_page(name, format, content, commit_details) 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 if is_enabled
gitaly_write_page(name, format, content, commit_details) gitaly_write_page(name, format, content, commit_details)
gollum_wiki.clear_cache gollum_wiki.clear_cache
...@@ -47,8 +48,9 @@ module Gitlab ...@@ -47,8 +48,9 @@ module Gitlab
end end
end end
# Disable because of https://gitlab.com/gitlab-org/gitlab-ce/issues/42094
def update_page(page_path, title, format, content, commit_details) 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 if is_enabled
gitaly_update_page(page_path, title, format, content, commit_details) gitaly_update_page(page_path, title, format, content, commit_details)
gollum_wiki.clear_cache gollum_wiki.clear_cache
...@@ -68,8 +70,9 @@ module Gitlab ...@@ -68,8 +70,9 @@ module Gitlab
end end
end end
# Disable because of https://gitlab.com/gitlab-org/gitlab-ce/issues/42039
def page(title:, version: nil, dir: nil) 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 if is_enabled
gitaly_find_page(title: title, version: version, dir: dir) gitaly_find_page(title: title, version: version, dir: dir)
else else
...@@ -192,7 +195,10 @@ module Gitlab ...@@ -192,7 +195,10 @@ module Gitlab
assert_type!(format, Symbol) assert_type!(format, Symbol)
assert_type!(commit_details, CommitDetails) 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 nil
rescue Gollum::DuplicatePageError => e rescue Gollum::DuplicatePageError => e
...@@ -210,7 +216,15 @@ module Gitlab ...@@ -210,7 +216,15 @@ module Gitlab
assert_type!(format, Symbol) assert_type!(format, Symbol)
assert_type!(commit_details, CommitDetails) 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 nil
end end
......
...@@ -8,8 +8,8 @@ msgid "" ...@@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gitlab 1.0.0\n" "Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-30 14:59+0100\n" "POT-Creation-Date: 2018-02-05 16:03+0100\n"
"PO-Revision-Date: 2018-01-30 14:59+0100\n" "PO-Revision-Date: 2018-02-05 16:03+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n" "Language: \n"
...@@ -23,6 +23,11 @@ msgid_plural "%d commits" ...@@ -23,6 +23,11 @@ msgid_plural "%d commits"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
msgid "%d issue" msgid "%d issue"
msgid_plural "%d issues" msgid_plural "%d issues"
msgstr[0] "" msgstr[0] ""
...@@ -157,6 +162,18 @@ msgstr "" ...@@ -157,6 +162,18 @@ msgstr ""
msgid "An error occurred while fetching sidebar data" msgid "An error occurred while fetching sidebar data"
msgstr "" 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" msgid "An error occurred while retrieving diff"
msgstr "" msgstr ""
...@@ -480,6 +497,24 @@ msgstr "" ...@@ -480,6 +497,24 @@ msgstr ""
msgid "CiStatus|running" msgid "CiStatus|running"
msgstr "" 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" msgid "CircuitBreakerApiLink|circuitbreaker api"
msgstr "" msgstr ""
...@@ -791,6 +826,9 @@ msgstr "" ...@@ -791,6 +826,9 @@ msgstr ""
msgid "Commits|An error occurred while fetching merge requests data." msgid "Commits|An error occurred while fetching merge requests data."
msgstr "" msgstr ""
msgid "Commits|Commit: %{commitText}"
msgstr ""
msgid "Commits|History" msgid "Commits|History"
msgstr "" msgstr ""
...@@ -890,6 +928,9 @@ msgstr "" ...@@ -890,6 +928,9 @@ msgstr ""
msgid "Copy URL to clipboard" msgid "Copy URL to clipboard"
msgstr "" msgstr ""
msgid "Copy branch name to clipboard"
msgstr ""
msgid "Copy commit SHA to clipboard" msgid "Copy commit SHA to clipboard"
msgstr "" msgstr ""
...@@ -1099,12 +1140,33 @@ msgstr "" ...@@ -1099,12 +1140,33 @@ msgstr ""
msgid "Environments|You don't have any environments right now." msgid "Environments|You don't have any environments right now."
msgstr "" msgstr ""
msgid "Error fetching contributors data."
msgstr ""
msgid "Error fetching labels."
msgstr ""
msgid "Error fetching network graph."
msgstr ""
msgid "Error fetching refs" msgid "Error fetching refs"
msgstr "" msgstr ""
msgid "Error fetching usage ping data."
msgstr ""
msgid "Error occurred when toggling the notification subscription" msgid "Error occurred when toggling the notification subscription"
msgstr "" 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" msgid "EventFilterBy|Filter by all"
msgstr "" msgstr ""
...@@ -1716,12 +1778,6 @@ msgstr "" ...@@ -1716,12 +1778,6 @@ msgstr ""
msgid "PipelineSchedules|Inactive" msgid "PipelineSchedules|Inactive"
msgstr "" msgstr ""
msgid "PipelineSchedules|Input variable key"
msgstr ""
msgid "PipelineSchedules|Input variable value"
msgstr ""
msgid "PipelineSchedules|Next Run" msgid "PipelineSchedules|Next Run"
msgstr "" msgstr ""
...@@ -1731,9 +1787,6 @@ msgstr "" ...@@ -1731,9 +1787,6 @@ msgstr ""
msgid "PipelineSchedules|Provide a short description for this pipeline" msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "" msgstr ""
msgid "PipelineSchedules|Remove variable row"
msgstr ""
msgid "PipelineSchedules|Take ownership" msgid "PipelineSchedules|Take ownership"
msgstr "" msgstr ""
...@@ -2116,6 +2169,9 @@ msgstr[1] "" ...@@ -2116,6 +2169,9 @@ msgstr[1] ""
msgid "Snippets" msgid "Snippets"
msgstr "" msgstr ""
msgid "Something went wrong on our end"
msgstr ""
msgid "Something went wrong on our end." msgid "Something went wrong on our end."
msgstr "" msgstr ""
...@@ -2424,6 +2480,18 @@ msgstr "" ...@@ -2424,6 +2480,18 @@ msgstr ""
msgid "There are problems accessing Git storage: " msgid "There are problems accessing Git storage: "
msgstr "" 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" msgid "This directory"
msgstr "" msgstr ""
...@@ -2635,6 +2703,9 @@ msgstr "" ...@@ -2635,6 +2703,9 @@ msgstr ""
msgid "Trigger this manual action" msgid "Trigger this manual action"
msgstr "" msgstr ""
msgid "Type %{value} to confirm:"
msgstr ""
msgid "Unable to reset project cache." msgid "Unable to reset project cache."
msgstr "" msgstr ""
...@@ -2719,6 +2790,12 @@ msgstr "" ...@@ -2719,6 +2790,12 @@ msgstr ""
msgid "WikiClone|Start Gollum and edit locally" msgid "WikiClone|Start Gollum and edit locally"
msgstr "" 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" msgid "WikiEmptyPageError|You are not allowed to create wiki pages"
msgstr "" msgstr ""
...@@ -2897,6 +2974,9 @@ msgstr[1] "" ...@@ -2897,6 +2974,9 @@ msgstr[1] ""
msgid "mrWidget|Cancel automatic merge" msgid "mrWidget|Cancel automatic merge"
msgstr "" msgstr ""
msgid "mrWidget|Check out branch"
msgstr ""
msgid "mrWidget|Checking ability to merge automatically" msgid "mrWidget|Checking ability to merge automatically"
msgstr "" msgstr ""
...@@ -2906,9 +2986,27 @@ msgstr "" ...@@ -2906,9 +2986,27 @@ msgstr ""
msgid "mrWidget|Cherry-pick this merge request in a new merge request" msgid "mrWidget|Cherry-pick this merge request in a new merge request"
msgstr "" msgstr ""
msgid "mrWidget|Closed"
msgstr ""
msgid "mrWidget|Closed by" msgid "mrWidget|Closed by"
msgstr "" 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" msgid "mrWidget|Merge"
msgstr "" msgstr ""
...@@ -2921,6 +3019,9 @@ msgstr "" ...@@ -2921,6 +3019,9 @@ msgstr ""
msgid "mrWidget|Merged by" msgid "mrWidget|Merged by"
msgstr "" msgstr ""
msgid "mrWidget|Plain diff"
msgstr ""
msgid "mrWidget|Refresh" msgid "mrWidget|Refresh"
msgstr "" msgstr ""
...@@ -2936,6 +3037,9 @@ msgstr "" ...@@ -2936,6 +3037,9 @@ msgstr ""
msgid "mrWidget|Remove source branch" msgid "mrWidget|Remove source branch"
msgstr "" msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
msgid "mrWidget|Resolve conflicts" msgid "mrWidget|Resolve conflicts"
msgstr "" msgstr ""
...@@ -2981,9 +3085,18 @@ msgstr "" ...@@ -2981,9 +3085,18 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled" msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "" msgstr ""
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
msgid "mrWidget|You can remove source branch now" msgid "mrWidget|You can remove source branch now"
msgstr "" msgstr ""
msgid "mrWidget|command line"
msgstr ""
msgid "mrWidget|into"
msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds" msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "" msgstr ""
......
require 'spec_helper' 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) } let(:user) { create(:user) }
before do before do
...@@ -143,6 +144,7 @@ describe 'User updates wiki page' do ...@@ -143,6 +144,7 @@ describe 'User updates wiki page' do
expect(page).to have_field('wiki[message]', with: 'Update home') expect(page).to have_field('wiki[message]', with: 'Update home')
fill_in(:wiki_content, with: 'My awesome wiki!') fill_in(:wiki_content, with: 'My awesome wiki!')
click_button('Save changes') click_button('Save changes')
expect(page).to have_content('Home') expect(page).to have_content('Home')
...@@ -151,4 +153,74 @@ describe 'User updates wiki page' do ...@@ -151,4 +153,74 @@ describe 'User updates wiki page' do
end end
end 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 end
require 'spec_helper' 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(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) } let(:project) { create(:project, namespace: user.namespace) }
let(:wiki_page) do let(:wiki_page) do
......
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 ...@@ -188,14 +188,37 @@ describe WikiPage do
end end
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 before do
create_page("Update", "content") create_page("Update", "content")
@page = wiki.find_page("Update") @page = wiki.find_page("Update")
end end
after do after do
destroy_page(@page.title) destroy_page(@page.title, @page.directory)
end end
context "with valid attributes" do context "with valid attributes" do
...@@ -233,6 +256,95 @@ describe WikiPage do ...@@ -233,6 +256,95 @@ describe WikiPage do
expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError) expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError)
end end
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 end
describe "#destroy" do describe "#destroy" do
...@@ -421,8 +533,8 @@ describe WikiPage do ...@@ -421,8 +533,8 @@ describe WikiPage do
wiki.wiki.write_page(name, :markdown, content, commit_details) wiki.wiki.write_page(name, :markdown, content, commit_details)
end end
def destroy_page(title) def destroy_page(title, dir = '')
page = wiki.wiki.page(title: title) page = wiki.wiki.page(title: title, dir: dir)
wiki.delete_page(page, "test commit") wiki.delete_page(page, "test commit")
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment