Commit ea9b3687 authored by Dan Knox's avatar Dan Knox

Replace current Wiki system with Gollum Wikis.

This commit replaces the old database backed Wiki system with the
excellent Gollum git based Wiki system.

The UI has been updated to allow for utilizing the extra features
that Gollum provides. Specifically:

* Edit page now allows you to choose the content format.
* Edit page allows you to provide a commit message for the change.
* History page now shows Format, Commit Message, and Commit Hash.
* A new Git Access page has been added with the Wiki Repo URL.
* The default page has been changed to Home from Index to match
the Gollum standard.

The old Wiki model has been left in tact to provide for the
development of a migration script that will move all content stored
in the old Wiki system into new Gollum Wikis.
parent 8e8372d5
...@@ -99,6 +99,13 @@ gem "colored" ...@@ -99,6 +99,13 @@ gem "colored"
# GitLab settings # GitLab settings
gem 'settingslogic' gem 'settingslogic'
# Wiki
# - Use latest master to resolve Gem dependency with Pygemnts
# github-linquist needs pygments 0.4.2 but Gollum 2.4.11
# requires pygments 0.3.2. The latest master Gollum has been updated
# to use pygments 0.4.2. Change this after next Gollum release.
gem "gollum", "~> 2.4.0", git: "git://github.com/github/gollum.git"
# Misc # Misc
gem "foreman" gem "foreman"
gem "git" gem "git"
......
GIT
remote: git://github.com/github/gollum.git
revision: 544d499ab170c9d9b355b7a0160afc74139ee2a4
specs:
gollum (2.4.11)
github-markdown (~> 0.5.3)
github-markup (>= 0.7.5, < 1.0.0)
grit (~> 2.5.0)
mustache (>= 0.99.4, < 1.0.0)
nokogiri (~> 1.5.6)
pygments.rb (~> 0.4.2)
sanitize (~> 2.0.3)
sinatra (~> 1.3.5)
stringex (~> 1.5.1)
useragent (~> 0.4.16)
GIT GIT
remote: https://github.com/ctran/annotate_models.git remote: https://github.com/ctran/annotate_models.git
revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
...@@ -139,6 +155,7 @@ GEM ...@@ -139,6 +155,7 @@ GEM
escape_utils (~> 0.2.3) escape_utils (~> 0.2.3)
mime-types (~> 1.19) mime-types (~> 1.19)
pygments.rb (>= 0.2.13) pygments.rb (>= 0.2.13)
github-markdown (0.5.3)
github-markup (0.7.5) github-markup (0.7.5)
gitlab-grack (1.0.0) gitlab-grack (1.0.0)
rack (~> 1.4.1) rack (~> 1.4.1)
...@@ -170,6 +187,10 @@ GEM ...@@ -170,6 +187,10 @@ GEM
grape-entity (0.2.0) grape-entity (0.2.0)
activesupport activesupport
multi_json (>= 1.3.2) multi_json (>= 1.3.2)
grit (2.5.0)
diff-lcs (~> 1.1)
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
grit_ext (0.6.2) grit_ext (0.6.2)
charlock_holmes (~> 0.6.9) charlock_holmes (~> 0.6.9)
growl (1.0.3) growl (1.0.3)
...@@ -231,7 +252,8 @@ GEM ...@@ -231,7 +252,8 @@ GEM
sprockets (~> 2.0) sprockets (~> 2.0)
multi_json (1.6.1) multi_json (1.6.1)
multi_xml (0.5.3) multi_xml (0.5.3)
multipart-post (1.2.0) multipart-post (1.1.5)
mustache (0.99.4)
mysql2 (0.3.11) mysql2 (0.3.11)
net-ldap (0.2.2) net-ldap (0.2.2)
nokogiri (1.5.6) nokogiri (1.5.6)
...@@ -365,6 +387,8 @@ GEM ...@@ -365,6 +387,8 @@ GEM
rspec-mocks (~> 2.12.0) rspec-mocks (~> 2.12.0)
rubyntlm (0.1.1) rubyntlm (0.1.1)
rubyzip (0.9.9) rubyzip (0.9.9)
sanitize (2.0.3)
nokogiri (>= 1.4.4, < 1.6)
sass (3.2.5) sass (3.2.5)
sass-rails (3.2.5) sass-rails (3.2.5)
railties (~> 3.2.0) railties (~> 3.2.0)
...@@ -418,6 +442,7 @@ GEM ...@@ -418,6 +442,7 @@ GEM
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
stamp (0.5.0) stamp (0.5.0)
state_machine (1.1.2) state_machine (1.1.2)
stringex (1.5.1)
temple (0.5.5) temple (0.5.5)
test_after_commit (0.0.1) test_after_commit (0.0.1)
therubyracer (0.10.2) therubyracer (0.10.2)
...@@ -440,6 +465,7 @@ GEM ...@@ -440,6 +465,7 @@ GEM
kgio (~> 2.6) kgio (~> 2.6)
rack rack
raindrops (~> 0.7) raindrops (~> 0.7)
useragent (0.4.16)
virtus (0.5.4) virtus (0.5.4)
backports (~> 2.6.1) backports (~> 2.6.1)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
...@@ -487,6 +513,7 @@ DEPENDENCIES ...@@ -487,6 +513,7 @@ DEPENDENCIES
gitlab_meta (= 5.0) gitlab_meta (= 5.0)
gitlab_omniauth-ldap (= 1.0.2) gitlab_omniauth-ldap (= 1.0.2)
gitlab_yaml_db (= 1.0.0) gitlab_yaml_db (= 1.0.0)
gollum (~> 2.4.0)!
gon gon
grape (~> 0.3.1) grape (~> 0.3.1)
grape-entity (~> 0.2.0) grape-entity (~> 0.2.0)
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
@import "sections/login.scss"; @import "sections/login.scss";
@import "sections/editor.scss"; @import "sections/editor.scss";
@import "sections/admin.scss"; @import "sections/admin.scss";
@import "sections/wiki.scss";
@import "highlight/white.scss"; @import "highlight/white.scss";
@import "highlight/dark.scss"; @import "highlight/dark.scss";
......
h3.page_title .edit-wiki-header {
width: 780px;
margin-left: auto;
margin-right: auto;
padding-right: 7px;
}
...@@ -2,58 +2,94 @@ class WikisController < ProjectResourceController ...@@ -2,58 +2,94 @@ class WikisController < ProjectResourceController
before_filter :authorize_read_wiki! before_filter :authorize_read_wiki!
before_filter :authorize_write_wiki!, only: [:edit, :create, :history] before_filter :authorize_write_wiki!, only: [:edit, :create, :history]
before_filter :authorize_admin_wiki!, only: :destroy before_filter :authorize_admin_wiki!, only: :destroy
before_filter :load_gollum_wiki
def pages def pages
@wiki_pages = @project.wikis.group(:slug).ordered @wiki_pages = @gollum_wiki.pages
end end
def show def show
@most_recent_wiki = @project.wikis.where(slug: params[:id]).ordered.first @wiki = @gollum_wiki.find_page(params[:id], params[:version_id])
if params[:version_id]
@wiki = @project.wikis.find(params[:version_id])
else
@wiki = @most_recent_wiki
end
if @wiki if @wiki
render 'show' render 'show'
else else
if can?(current_user, :write_wiki, @project) return render('empty') unless can?(current_user, :write_wiki, @project)
@wiki = @project.wikis.new(slug: params[:id]) @wiki = WikiPage.new(@gollum_wiki)
render 'edit' @wiki.title = params[:id]
else
render 'empty' render 'edit'
end
end end
end end
def edit def edit
@wiki = @project.wikis.where(slug: params[:id]).ordered.first @wiki = @gollum_wiki.find_page(params[:id])
@wiki = Wiki.regenerate_from @wiki end
def update
@wiki = @gollum_wiki.find_page(params[:id])
return render('empty') unless can?(current_user, :write_wiki, @project)
if @wiki.update(content, format, message)
redirect_to [@project, @wiki], notice: 'Wiki was successfully updated.'
else
render 'edit'
end
end end
def create def create
@wiki = @project.wikis.new(params[:wiki]) @wiki = WikiPage.new(@gollum_wiki)
@wiki.user = current_user
if @wiki.create(wiki_params)
respond_to do |format| redirect_to project_wiki_path(@project, @wiki), notice: 'Wiki was successfully updated.'
if @wiki.save else
format.html { redirect_to [@project, @wiki], notice: 'Wiki was successfully updated.' } render action: "edit"
else
format.html { render action: "edit" }
end
end end
end end
def history def history
@wiki_pages = @project.wikis.where(slug: params[:id]).ordered unless @wiki = @gollum_wiki.find_page(params[:id])
redirect_to project_wiki_path(@project, :home), notice: "Page not found"
end
end end
def destroy def destroy
@wikis = @project.wikis.where(slug: params[:id]).delete_all @wiki = @gollum_wiki.find_page(params[:id])
@wiki.delete if @wiki
redirect_to project_wiki_path(@project, :home), notice: "Page was successfully deleted"
end
respond_to do |format| def git_access
format.html { redirect_to project_wiki_path(@project, :index), notice: "Page was successfully deleted" }
end
end end
private
def load_gollum_wiki
@gollum_wiki = GollumWiki.new(@project, current_user)
# Call #wiki to make sure the Wiki Repo is initialized
@gollum_wiki.wiki
rescue GollumWiki::CouldNotCreateWikiError => ex
flash[:notice] = "Could not create Wiki Repository at this time. Please try again later."
redirect_to @project
return false
end
def wiki_params
params[:wiki].slice(:title, :content, :format, :message)
end
def content
params[:wiki][:content]
end
def format
params[:wiki][:format]
end
def message
params[:wiki][:message]
end
end end
class GollumWiki
MARKUPS = {
"Markdown" => :markdown,
"Textile" => :textile,
"RDoc" => :rdoc,
"Org-mode" => :org,
"Creole" => :creole,
"reStructuredText" => :rest,
"AsciiDoc" => :asciidoc,
"MediaWiki" => :mediawiki,
"Pod" => :post
}
class CouldNotCreateWikiError < StandardError; end
# Returns a string describing what went wrong after
# an operation fails.
attr_reader :error_message
def initialize(project, user = nil)
@project = project
@user = user
end
def path_with_namespace
@project.path_with_namespace + ".wiki"
end
def url_to_repo
gitlab_shell.url_to_repo(path_with_namespace)
end
def ssh_url_to_repo
url_to_repo
end
def http_url_to_repo
http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
end
# Returns the Gollum::Wiki object.
def wiki
@wiki ||= begin
Gollum::Wiki.new(path_to_repo)
rescue Grit::NoSuchPathError
create_repo!
end
end
# Returns an Array of Gitlab WikiPage instances or an
# empty Array if this Wiki has no pages.
def pages
wiki.pages.map { |page| WikiPage.new(self, page, true) }
end
# Returns the last 30 Commit objects accross the entire
# repository.
def recent_history
Commit.fresh_commits(wiki.repo, 30)
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)
if page = wiki.page(title, version)
WikiPage.new(self, page, true)
else
nil
end
end
def create_page(title, content, format = :markdown, message = nil)
commit = commit_details(:created, message, title)
wiki.write_page(title, format, content, commit)
rescue Gollum::DuplicatePageError => e
@error_message = "Duplicate page: #{e.message}"
return false
end
def update_page(page, content, format = :markdown, message = nil)
commit = commit_details(:updated, message, page.title)
wiki.update_page(page, page.name, format, content, commit)
end
def delete_page(page, message = nil)
wiki.delete_page(page, commit_details(:deleted, message, page.title))
end
private
def create_repo!
if gitlab_shell.add_repository(path_with_namespace)
Gollum::Wiki.new(path_to_repo)
else
raise CouldNotCreateWikiError
end
end
def commit_details(action, message = nil, title = nil)
commit_message = message || default_message(action, title)
{email: @user.email, name: @user.name, message: commit_message}
end
def default_message(action, title)
"#{@user.username} #{action} page: #{title}"
end
def gitlab_shell
@gitlab_shell ||= Gitlab::Shell.new
end
def path_to_repo
@path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
end
end
class WikiPage
include ActiveModel::Validations
include ActiveModel::Conversion
include StaticModel
extend ActiveModel::Naming
def self.primary_key
'slug'
end
def self.model_name
ActiveModel::Name.new(self, nil, 'wiki')
end
def to_key
[:slug]
end
validates :title, presence: true
validates :content, presence: true
# The Gitlab GollumWiki instance.
attr_reader :wiki
# The raw Gollum::Page instance.
attr_reader :page
# The attributes Hash used for storing and validating
# new Page values before writing to the Gollum repository.
attr_accessor :attributes
def initialize(wiki, page = nil, persisted = false)
@wiki = wiki
@page = page
@persisted = persisted
@attributes = {}.with_indifferent_access
set_attributes if persisted?
end
# The escaped URL path of this page.
def slug
@attributes[:slug]
end
alias :to_param :slug
# The formatted title of this page.
def title
@attributes[:title] || ""
end
# Sets the title of this page.
def title=(new_title)
@attributes[:title] = new_title
end
# The raw content of this page.
def content
@attributes[:content]
end
# The processed/formatted content of this page.
def formatted_content
@attributes[:formatted_content]
end
# The markup format for the page.
def format
@attributes[:format] || :markdown
end
# The commit message for this page version.
def message
version.try(:message)
end
# The Gitlab Commit instance for this page.
def version
return nil unless persisted?
@version ||= Commit.new(@page.version)
end
# Returns an array of Gitlab Commit instances.
def versions
return [] unless persisted?
@page.versions.map { |v| Commit.new(v) }
end
# Returns the Date that this latest version was
# created on.
def created_at
@page.version.date
end
# Returns boolean True or False if this instance
# is an old version of the page.
def historical?
@page.historical?
end
# Returns boolean True or False if this instance
# has been fully saved to disk or not.
def persisted?
@persisted == true
end
# Creates a new Wiki Page.
#
# attr - Hash of attributes to set on the new page.
# :title - The title for the new page.
# :content - The raw markup content.
# :format - Optional symbol representing the
# content format. Can be any type
# listed in the GollumWiki::MARKUPS
# Hash.
# :message - Optional commit message to set on
# the new page.
#
# Returns the String SHA1 of the newly created page
# or False if the save was unsuccessful.
def create(attr = {})
@attributes.merge!(attr)
save :create_page, title, content, format, message
end
# Updates an existing Wiki Page, creating a new version.
#
# new_content - The raw markup content to replace the existing.
# format - Optional symbol representing the content format.
# See GollumWiki::MARKUPS Hash for available formats.
# message - Optional commit message to set on the new version.
#
# Returns the String SHA1 of the newly created page
# or False if the save was unsuccessful.
def update(new_content = "", format = :markdown, message = nil)
@attributes[:content] = new_content
@attributes[:format] = format
save :update_page, @page, content, format, message
end
# Destroys the WIki Page.
#
# Returns boolean True or False.
def delete
if wiki.delete_page(@page)
true
else
false
end
end
private
def set_attributes
attributes[:slug] = @page.escaped_url_path
attributes[:title] = @page.title
attributes[:content] = @page.raw_data
attributes[:formatted_content] = @page.formatted_data
attributes[:format] = @page.format
end
def save(method, *args)
if valid? && wiki.send(method, *args)
@page = wiki.wiki.paged(title)
set_attributes
@persisted = true
else
errors.add(:base, wiki.error_message) if wiki.error_message
@persisted = false
end
@persisted
end
end
...@@ -18,6 +18,11 @@ class ProjectObserver < ActiveRecord::Observer ...@@ -18,6 +18,11 @@ class ProjectObserver < ActiveRecord::Observer
project.path_with_namespace project.path_with_namespace
) )
GitlabShellWorker.perform_async(
:remove_repository,
project.path_with_namespace + ".wiki"
)
project.satellite.destroy project.satellite.destroy
log_info("Project \"#{project.name}\" was removed") log_info("Project \"#{project.name}\" was removed")
......
...@@ -41,6 +41,6 @@ ...@@ -41,6 +41,6 @@
- if @project.wiki_enabled - if @project.wiki_enabled
= nav_link(controller: :wikis) do = nav_link(controller: :wikis) do
= link_to 'Wiki', project_wiki_path(@project, :index) = link_to 'Wiki', project_wiki_path(@project, :home)
.content= yield .content= yield
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
.ui-box.ui-box-show .ui-box.ui-box-show
.ui-box-head .ui-box-head
= f.label :title %h3.page_title
.input= f.text_field :title, class: 'span8' .edit-wiki-header
= f.hidden_field :slug = @wiki.title.titleize
= f.hidden_field :title, value: @wiki.title
= f.select :format, options_for_select(GollumWiki::MARKUPS, {selected: @wiki.format}), {}, class: "pull-right input-medium"
= f.label :format, class: "pull-right", style: "padding-right: 20px;"
.ui-box-body .ui-box-body
.input .input
%span.cgray %span.cgray
...@@ -22,6 +25,9 @@ ...@@ -22,6 +25,9 @@
.ui-box-bottom .ui-box-bottom
= f.label :content = f.label :content
.input= f.text_area :content, class: 'span8 js-gfm-input' .input= f.text_area :content, class: 'span8 js-gfm-input'
.ui-box-bottom
= f.label :commit_message
.input= f.text_field :message, class: 'span8'
.actions .actions
= f.submit 'Save', class: "btn-save btn" = f.submit 'Save', class: "btn-save btn"
= link_to "Cancel", project_wiki_path(@project, :index), class: "btn btn-cancel" = link_to "Cancel", project_wiki_path(@project, :index), class: "btn btn-cancel"
%span.pull-right
= link_to project_wiki_path(@project, :home), class: "btn btn-small grouped" do
Home
= link_to pages_project_wikis_path(@project), class: "btn btn-small grouped" do
Pages
- if (@wiki && @wiki.persisted?)
= link_to history_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
History
- if can?(current_user, :write_wiki, @project)
- if @wiki && @wiki.persisted?
= link_to edit_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
%i.icon-edit
Edit
= link_to git_access_project_wikis_path(@project), class: "btn btn-small grouped" do
%i.icon-download-alt
Git Access
%h3.page_title Editing page %h3.page_title
Editing page
= render partial: 'main_links'
%hr %hr
= render 'form' = render 'form'
.pull-right .pull-right
- if can? current_user, :admin_wiki, @project - if can? current_user, :admin_wiki, @project
= link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn btn-small btn-remove" do = link_to project_wikis_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn btn-small btn-remove" do
Delete this page Delete this page
\ No newline at end of file
%h3.page_title
Git Access
%strong= @gollum_wiki.path_with_namespace
= render partial: 'main_links'
%br
.content
.project_clone_panel
.row
.span7
.form-horizontal
.input-prepend.project_clone_holder
%button{class: "btn active", :"data-clone" => @gollum_wiki.ssh_url_to_repo} SSH
%button{class: "btn", :"data-clone" => @gollum_wiki.http_url_to_repo}= Gitlab.config.gitlab.protocol.upcase
= text_field_tag :project_clone, @gollum_wiki.url_to_repo, class: "one_click_select input-xxlarge", readonly: true
.git-empty
%fieldset
%legend Install Gollum:
%pre.dark
:preserve
gem install gollum
%legend Clone Your Wiki:
%pre.dark
:preserve
git clone #{@gollum_wiki.path_with_namespace}.git
cd #{@gollum_wiki.path_with_namespace}
%legend Start Gollum And Edit Locally:
%pre.dark
:preserve
gollum
== Sinatra/1.3.5 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.5.0 codename Knife)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
%h3.page_title %h3.page_title
%span.cgray History for %span.cgray History for
= @wiki_pages.first.title = @wiki.title.titleize
= render partial: 'main_links'
%br %br
%table %table
%thead %thead
%tr %tr
%th Page version %th Page version
%th Author
%th Commit Message
%th Last updated %th Last updated
%th Updated by %th Format
%tbody %tbody
- @wiki_pages.each_with_index do |wiki_page, i| - @wiki.versions.each do |version|
- commit = CommitDecorator.new(version)
%tr %tr
%td %td
%strong = link_to project_wiki_path(@project, @wiki, version_id: commit.id) do
= link_to project_wiki_path(@project, wiki_page, version_id: wiki_page.id) do = commit.short_id
Version %td= commit.author_link avatar: true, size: 24
= @wiki_pages.count - i %td
= commit.title
%td %td
= wiki_page.created_at.to_s(:short) = time_ago_in_words(version.date)
(#{time_ago_in_words(wiki_page.created_at)} ago
ago) %td
%td= link_to_member(@project, wiki_page.user) %strong
= @wiki.page.wiki.page(@wiki.page.name, commit.id).try(:format)
%h3.page_title All Pages %h3.page_title
All Pages
= render partial: 'main_links'
%br %br
%table %table
%thead %thead
%tr %tr
%th Title %th Title
%th Slug %th Format
%th Last updated %th Last updated
%th Updated by %th Updated by
%tbody %tbody
- @wiki_pages.each do |wiki_page| - @wiki_pages.each do |wiki_page|
%tr %tr
%td %td
%strong= link_to wiki_page.title, project_wiki_path(@project, wiki_page) %strong= link_to wiki_page.title.titleize, project_wiki_path(@project, wiki_page)
%td= wiki_page.slug %td
%strong= wiki_page.format
%td %td
= wiki_page.created_at.to_s(:short) do = wiki_page.created_at.to_s(:short) do
(#{time_ago_in_words(wiki_page.created_at)} (#{time_ago_in_words(wiki_page.created_at)}
ago) ago)
%td= link_to_member(@project, wiki_page.user) - commit = CommitDecorator.decorate(wiki_page.version)
%td= commit.author_link avatar: true, size: 24
%h3.page_title %h3.page_title
= @wiki.title = @wiki.title.titleize
%span.pull-right = render partial: 'main_links'
= link_to pages_project_wikis_path(@project), class: "btn btn-small grouped" do
Pages
- if can? current_user, :write_wiki, @project
= link_to history_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
History
= link_to edit_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
%i.icon-edit
Edit
%br %br
- if @wiki != @most_recent_wiki - if @wiki.historical?
.warning_message .warning_message
This is an old version of this page. This is an old version of this page.
You can view the #{link_to "most recent version", project_wiki_path(@project, @wiki)} or browse the #{link_to "history", history_project_wiki_path(@project, @wiki)}. You can view the #{link_to "most recent version", project_wiki_path(@project, @wiki)} or browse the #{link_to "history", history_project_wiki_path(@project, @wiki)}.
...@@ -18,6 +10,7 @@ ...@@ -18,6 +10,7 @@
.file_holder .file_holder
.file_content.wiki .file_content.wiki
= preserve do = preserve do
= markdown @wiki.content = @wiki.formatted_content.html_safe
%p.time Last edited by #{link_to_member @project, @wiki.user}, #{time_ago_in_words @wiki.created_at} ago - commit = CommitDecorator.new(@wiki.version)
%p.time Last edited by #{commit.author_link(avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago
...@@ -185,6 +185,8 @@ Gitlab::Application.routes.draw do ...@@ -185,6 +185,8 @@ Gitlab::Application.routes.draw do
resources :wikis, only: [:show, :edit, :destroy, :create] do resources :wikis, only: [:show, :edit, :destroy, :create] do
collection do collection do
get :pages get :pages
put ':id' => 'wikis#update'
get :git_access
end end
member do member do
......
...@@ -12,10 +12,18 @@ module Gitlab ...@@ -12,10 +12,18 @@ module Gitlab
# ref - branch name # ref - branch name
# #
get "/allowed" do get "/allowed" do
# Check for *.wiki repositories.
# Strip out the .wiki from the pathname before finding the
# project. This applies the correct project permissions to
# the wiki repository as well.
project_path = params[:project]
project_path.gsub!(/\.wiki/,'') if project_path =~ /\.wiki/
key = Key.find(params[:key_id]) key = Key.find(params[:key_id])
project = Project.find_with_namespace(params[:project]) project = Project.find_with_namespace(project_path)
git_cmd = params[:action] git_cmd = params[:action]
if key.is_deploy_key if key.is_deploy_key
project == key.project && git_cmd == 'git-upload-pack' project == key.project && git_cmd == 'git-upload-pack'
else else
......
...@@ -208,24 +208,4 @@ describe "Gitlab Flavored Markdown" do ...@@ -208,24 +208,4 @@ describe "Gitlab Flavored Markdown" do
end end
end end
describe "for wikis" do
before do
visit project_wiki_path(project, :index)
fill_in "Title", with: "Circumvent ##{issue.id}"
fill_in "Content", with: "# Other pages\n\n* [Foo](foo)\n* [Bar](bar)\n\nAlso look at ##{issue.id} :-)"
click_on "Save"
end
it "should NOT render title in wikis#show" do
within(".content h3") do # page title
page.should have_content("Circumvent ##{issue.id}")
page.should_not have_link("##{issue.id}")
end
end
it "should render content in wikis#show" do
page.should have_link("##{issue.id}")
end
end
end end
require "spec_helper"
describe GollumWiki do
def create_temp_repo(path)
FileUtils.mkdir_p path
command = "git init --quiet #{path};"
system(command)
end
def remove_temp_repo(path)
FileUtils.rm_rf path
end
def commit_details
commit = {name: user.name, email: user.email, message: "test commit"}
end
def create_page(name, content)
subject.wiki.write_page(name, :markdown, content, commit_details)
end
def destroy_page(page)
subject.wiki.delete_page(page, commit_details)
end
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:user) { project.owner }
let(:gitlab_shell) { Gitlab::Shell.new }
subject { GollumWiki.new(project, user) }
before do
create_temp_repo(subject.send(:path_to_repo))
end
describe "#path_with_namespace" do
it "returns the project path with namespace with the .wiki extension" do
subject.path_with_namespace.should == project.path_with_namespace + ".wiki"
end
end
describe "#url_to_repo" do
it "returns the correct ssh url to the repo" do
subject.url_to_repo.should == gitlab_shell.url_to_repo(subject.path_with_namespace)
end
end
describe "#ssh_url_to_repo" do
it "equals #url_to_repo" do
subject.ssh_url_to_repo.should == subject.url_to_repo
end
end
describe "#http_url_to_repo" do
it "provides the full http url to the repo" do
gitlab_url = Gitlab.config.gitlab.url
repo_http_url = "#{gitlab_url}/#{subject.path_with_namespace}.git"
subject.http_url_to_repo.should == repo_http_url
end
end
describe "#wiki" do
it "contains a Gollum::Wiki instance" do
subject.wiki.should be_a Gollum::Wiki
end
before do
Gitlab::Shell.any_instance.stub(:add_repository) do
create_temp_repo("#{Rails.root}/tmp/test-git-base-path/non-existant.wiki.git")
end
project.stub(:path_with_namespace).and_return("non-existant")
end
it "creates a new wiki repo if one does not yet exist" do
wiki = GollumWiki.new(project, user)
wiki.create_page("index", "test content").should_not == false
FileUtils.rm_rf wiki.send(:path_to_repo)
end
it "raises CouldNotCreateWikiError if it can't create the wiki repository" do
Gitlab::Shell.any_instance.stub(:add_repository).and_return(false)
expect { GollumWiki.new(project, user).wiki }.to raise_exception(GollumWiki::CouldNotCreateWikiError)
end
end
describe "#pages" do
before do
create_page("index", "This is an awesome new Gollum Wiki")
@pages = subject.pages
end
after do
destroy_page(@pages.first.page)
end
it "returns an array of WikiPage instances" do
@pages.first.should be_a WikiPage
end
it "returns the correct number of pages" do
@pages.count.should == 1
end
end
describe "#find_page" do
before do
create_page("index page", "This is an awesome Gollum Wiki")
end
after do
destroy_page(subject.pages.first.page)
end
it "returns the latest version of the page if it exists" do
page = subject.find_page("index page")
page.title.should == "index page"
end
it "returns nil if the page does not exist" do
subject.find_page("non-existant").should == nil
end
it "can find a page by slug" do
page = subject.find_page("index-page")
page.title.should == "index page"
end
it "returns a WikiPage instance" do
page = subject.find_page("index page")
page.should be_a WikiPage
end
end
describe "#create_page" do
after do
destroy_page(subject.pages.first.page)
end
it "creates a new wiki page" do
subject.create_page("test page", "this is content").should_not == false
subject.pages.count.should == 1
end
it "returns false when a duplicate page exists" do
subject.create_page("test page", "content")
subject.create_page("test page", "content").should == false
end
it "stores an error message when a duplicate page exists" do
2.times { subject.create_page("test page", "content") }
subject.error_message.should =~ /Duplicate page:/
end
it "sets the correct commit message" do
subject.create_page("test page", "some content", :markdown, "commit message")
subject.pages.first.page.version.message.should == "commit message"
end
end
describe "#update_page" do
before do
create_page("update-page", "some content")
@gollum_page = subject.wiki.paged("update-page")
subject.update_page(@gollum_page, "some other content", :markdown, "updated page")
@page = subject.pages.first.page
end
after do
destroy_page(@page)
end
it "updates the content of the page" do
@page.raw_data.should == "some other content"
end
it "sets the correct commit message" do
@page.version.message.should == "updated page"
end
end
describe "#delete_page" do
before do
create_page("index", "some content")
@page = subject.wiki.paged("index")
end
it "deletes the page" do
subject.delete_page(@page)
subject.pages.count.should == 0
end
end
end
require "spec_helper"
describe WikiPage do
def create_temp_repo(path)
FileUtils.mkdir_p path
command = "git init --quiet #{path};"
system(command)
end
def remove_temp_repo(path)
FileUtils.rm_rf path
end
def commit_details
commit = {name: user.name, email: user.email, message: "test commit"}
end
def create_page(name, content)
wiki.wiki.write_page(name, :markdown, content, commit_details)
end
def destroy_page(title)
page = wiki.wiki.paged(title)
wiki.wiki.delete_page(page, commit_details)
end
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:user) { project.owner }
let(:wiki) { GollumWiki.new(project, user) }
subject { WikiPage.new(wiki) }
before do
create_temp_repo(wiki.send(:path_to_repo))
end
describe "#initialize" do
context "when initialized with an existing gollum page" do
before do
create_page("test page", "test content")
@page = wiki.wiki.paged("test page")
@wiki_page = WikiPage.new(wiki, @page, true)
end
it "sets the slug attribute" do
@wiki_page.slug.should == "test-page"
end
it "sets the title attribute" do
@wiki_page.title.should == "test page"
end
it "sets the formatted content attribute" do
@wiki_page.content.should == "test content"
end
it "sets the format attribute" do
@wiki_page.format.should == :markdown
end
it "sets the message attribute" do
@wiki_page.message.should == "test commit"
end
it "sets the version attribute" do
@wiki_page.version.should be_a Commit
end
end
end
describe "validations" do
before do
subject.attributes = {title: 'title', content: 'content'}
end
it "validates presence of title" do
subject.attributes.delete(:title)
subject.valid?.should be_false
end
it "validates presence of content" do
subject.attributes.delete(:content)
subject.valid?.should be_false
end
end
before do
@wiki_attr = {title: "Index", content: "Home Page", format: "markdown"}
end
describe "#create" do
after do
destroy_page("Index")
end
context "with valid attributes" do
it "saves the wiki page" do
subject.create(@wiki_attr)
wiki.find_page("Index").should_not be_nil
end
it "returns true" do
subject.create(@wiki_attr).should == true
end
end
end
describe "#update" do
before do
create_page("Update", "content")
@page = wiki.find_page("Update")
end
after do
destroy_page("Update")
end
context "with valid attributes" do
it "updates the content of the page" do
@page.update("new content")
@page = wiki.find_page("Update")
end
it "returns true" do
@page.update("more content").should be_true
end
end
end
describe "#destroy" do
before do
create_page("Delete Page", "content")
@page = wiki.find_page("Delete Page")
end
it "should delete the page" do
@page.delete
wiki.pages.should be_empty
end
it "should return true" do
@page.delete.should == true
end
end
describe "#versions" do
before do
create_page("Update", "content")
@page = wiki.find_page("Update")
end
after do
destroy_page("Update")
end
it "returns an array of all commits for the page" do
3.times { |i| @page.update("content #{i}") }
@page.versions.count.should == 4
end
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