Merge branch 'use_gollum_wikis' of https://github.com/DanKnox/gitlabhq into DanKnox-use_gollum_wikis

Conflicts:
	app/views/layouts/project_resource.html.haml
	app/views/wikis/edit.html.haml
	app/views/wikis/pages.html.haml
	app/views/wikis/show.html.haml
	spec/features/gitlab_flavored_markdown_spec.rb
This commit is contained in:
Dmitriy Zaporozhets 2013-03-15 16:55:07 +02:00
commit 71ab011a17
30 changed files with 1252 additions and 86 deletions

118
app/models/gollum_wiki.rb Normal file
View file

@ -0,0 +1,118 @@
class GollumWiki
MARKUPS = {
"Markdown" => :markdown,
"RDoc" => :rdoc
}
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

181
app/models/wiki_page.rb Normal file
View file

@ -0,0 +1,181 @@
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