Compare commits

...

86 Commits

Author SHA1 Message Date
Tom Preston-Werner 996f81d63d Release 1.1.0 2010-10-28 12:18:27 -07:00
Marko Anastasov 16ef859073 Ignore case when matching image paths.
Otherwise images with file extensions in caps don't get rendered.
2010-10-12 12:07:07 +02:00
rick e7b1265873 Gollum::Wiki#size returns 0 if the repo is invalid or empty 2010-10-11 17:40:09 -07:00
rick c0f8c897e7 update gemspec file listing 2010-10-11 16:58:22 -07:00
rick 33aad801bd update history 2010-10-06 13:20:29 -07:00
rick dd7dddddcf Revert "Gollum::Wiki#pages come back sorted by title, not permalink or the default ordering from git ls-tree."
This reverts commit e37a8b9da4.
2010-10-06 13:17:47 -07:00
rick 251d5c8201 add to history 2010-09-30 17:20:31 -07:00
rick 4dbe3ea844 ensures rel="nofollow" is added to all anchors if a page is retrieved with a SHA 2010-09-30 17:19:37 -07:00
rick cc929bbc56 tomdoc'd 2010-09-30 15:36:14 -07:00
rick 5e59e39d67 add to history 2010-09-30 15:32:38 -07:00
rick 05a7b4c06c Allow users to pass anchors to page links.
http://github.com/github/gollum/issues/\#issue/21
2010-09-30 15:32:02 -07:00
rick 7924db8e01 mention cgi escapage and git grep in the history 2010-09-30 14:26:27 -07:00
rick 4b313944fe merge 2010-09-30 14:22:18 -07:00
rick 9786f5f347 Merge branch 'master' into special-chars-in-page-names 2010-09-30 14:02:39 -07:00
Tom Preston-Werner 42985dc5c1 Explicitly set default port to 4567. 2010-09-29 14:42:24 -07:00
Tom Preston-Werner ee6b71ff80 Change 'bind' CLI option to 'host'. Set default to 127.0.0.1. Closes #47. 2010-09-29 14:40:36 -07:00
Tom Preston-Werner cdf75d20ef Merge remote branch 'etaque/sinatra-options' 2010-09-29 13:56:03 -07:00
Tom Preston-Werner 1e2932fd21 Merge remote branch 'henrikh/test-sections' 2010-09-29 13:09:08 -07:00
rick 4bb7d53854 history update 2010-09-16 09:23:02 -07:00
rick e37a8b9da4 Gollum::Wiki#pages come back sorted by title, not permalink or the default ordering from git ls-tree. 2010-09-16 09:16:42 -07:00
Emilien Taque 48bfe954d1 add Sinatra --bind option through gollum binary 2010-09-15 22:53:15 +02:00
rick 9cc8790d4f history lesson 2010-09-13 16:09:05 -07:00
rick d51f42e647 theres no blank? in ruby 2010-09-13 15:49:10 -07:00
rick 430436ce8d handle non strings passed to Page.cname 2010-09-13 15:48:54 -07:00
rick e774ceaf1f dont bomb when trying to find a page with a blank name 2010-09-12 20:04:21 -07:00
rick 42bd6c221a invalid shas return empty treemaps 2010-09-03 10:59:30 -07:00
Paul Baumgart 50e9a42503 fix documentation for Wiki.size 2010-09-02 20:30:13 -07:00
Paul Baumgart 5fcb5d971a Add support for RFC 1738 special characters in page names.
Escape all links and redirects to support this. Some changes to app.rb
necessary for correct routing by Sinatra.
2010-09-01 22:02:19 -07:00
Jon Frisby e9239050e0 Properly handle pages that exist in sub-dirs in search results 2010-08-31 10:48:10 +02:00
Jon Frisby 50c207ad91 Update gemspec with search files 2010-08-31 10:47:51 +02:00
rick 7c70174725 handle invalid options 2010-08-30 18:50:02 -07:00
rick e0d234c255 use grit to get the file's mime type, as suggested.
http://github.com/github/gollum/commit/6de9ddfd3f79a9cb320aab3c43b8e0a912107b2e#commitcomment-137656
2010-08-30 18:25:48 -07:00
rick bf37f44970 pull default name/email for commits from wiki repo's git config 2010-08-30 18:11:03 -07:00
rick 847e6c00a4 Merge branch 'master' of github.com:github/gollum 2010-08-30 18:04:36 -07:00
Jon Frisby 6de9ddfd3f Make an attempt at setting a proper mime-type when showing a file.
Prevents things like having the browser show raw binary data when you have a PDF in your repo.
2010-08-31 09:04:27 +08:00
Jon Frisby 1f8a67598a Use Grit to determine committer instead of executing a sub-shell and calling the git CLI. 2010-08-31 09:04:27 +08:00
Jon Frisby 515f8610c4 Make --version not cough up a furball.
Commit 8c625419b8 moved the require down,
which broke --version.
2010-08-31 08:59:56 +08:00
rick ba18cbebe8 more tree_map tests 2010-08-30 17:56:03 -07:00
rick 646c8e21b2 Add Wiki#size to efficiently count pages without loading them. 2010-08-30 17:52:20 -07:00
rick 6dab4f7fe6 Wiki#pages uses the treemap 2010-08-30 17:45:32 -07:00
rick 7e2b1fdbc6 Wiki#tree_map_for returns an array of BlobEntry instances 2010-08-30 17:31:19 -07:00
rick 6f077702e1 Page#find_page_in_this_tree is redundant 2010-08-30 17:04:30 -07:00
Dean Strelau f4c4b2e49c Update development dependencies. Closes github#18
Tests require a few markdown libraries to pass.
2010-08-30 16:38:01 -07:00
Tom Preston-Werner db1ccc4525 DRY up test commit details. 2010-08-30 16:38:01 -07:00
Tom Preston-Werner dddb73672a Minor readme typo and various whitespace fixups. 2010-08-30 16:38:01 -07:00
Tom Preston-Werner 94f05b0796 Update working dir (if present) when edited via the API. Closes #6. 2010-08-30 16:37:59 -07:00
Sirupsen 6d3b40c1d4 Using Grit instead of backticked bash.
A bit unclear what's going on though, would be more explicit to say:
{:count => query}, however Grit::Git#transform_options converts to this
syntax:
`--count='query'` and `git grep` can't take this syntax, it has to be:
`git grep --count query`, and this is why we're using :c, and not
:count. As {:c => query} converts to: `git grep -c 'query'` which works
as expected.

Linked to this commit, for above information in comment.

Updated comment in Wiki.search to link describing commit.
2010-08-29 15:25:04 +02:00
Sirupsen 45eb364a6d Refactoring of Wiki.search. 2010-08-29 14:30:30 +02:00
Henrik Hansen 959f02b50e Use correct capitalization of TeX 2010-08-29 14:26:14 +02:00
Henrik Hansen 49d88a0370 Add search API and update frontend
The frontend has been updated to use the new search API.
2010-08-29 13:58:06 +02:00
Henrik Hansen ed41152228 Refactor of search view 2010-08-29 13:54:38 +02:00
Henrik Hansen 294847ed99 Remove display of search code 2010-08-29 13:54:21 +02:00
Henrik Hansen 8301428974 Add sections to clean up markup test code 2010-08-29 10:08:08 +02:00
rick 0500c7e10c cache the ref => sha lookup 2010-08-24 12:39:26 -07:00
rick 3eeed9ba1e update Wiki#find_page_in_tree to use cached tree map 2010-08-24 12:15:11 -07:00
rick 292f6ec8dc update Wiki#find_page_in_this_tree to use the new cached tree map. 2010-08-24 11:47:20 -07:00
rick 068a902a00 don't modify path names in cached wiki treemaps 2010-08-24 11:47:02 -07:00
rick d606511fdf use cached tree map when finding files 2010-08-24 11:29:39 -07:00
rick cc3d9529cc add a cached Wiki#tree_map_for method 2010-08-24 11:24:49 -07:00
rick 74ca65b045 history updates 2010-08-23 16:39:10 -07:00
rick 05283347b0 more descriptive irb output
also, code poetry arguments
2010-08-23 16:35:17 -07:00
rick 99995f7364 convert $path global to a gollum_path sinatra setting 2010-08-23 16:16:39 -07:00
rick 8c625419b8 add irb option for the cli script 2010-08-23 16:13:38 -07:00
Henrik Hansen d1003f5331 Change search-field to use type="search"
The search-field will now show with a little magnifying-glass on Webkit
based browsers.
type="search" is part of HTML5.
2010-08-23 16:59:47 +02:00
Tobias Adam 4905ce99da Add a very rough and dirty search mechanism that uses Git’s grep. 2010-08-22 23:17:54 +02:00
Tom Preston-Werner 48b143c6ed Update history for massive performance optimization. 2010-08-19 18:21:26 -07:00
Tom Preston-Werner dae2e0c79c Remove obsolete tree map methods. 2010-08-19 17:40:05 -07:00
Tom Preston-Werner 9b32d3bfb1 Update Wiki#delete_page to use Index#read_tree awesomes. 2010-08-19 17:37:49 -07:00
Tom Preston-Werner b1fc173a3f Update Wiki#update_page to use Index#read_tree goodness. 2010-08-19 17:35:18 -07:00
Tom Preston-Werner 6a53e3d037 Clean up some whitespace. 2010-08-19 15:43:26 -07:00
Tom Preston-Werner 15879a5a88 Use Index#read_tree for Wiki#write_page instead of rebuilding the entire index. 2010-08-19 15:42:36 -07:00
rick c6e2acbf62 history is written by the victors 2010-08-16 17:39:17 -07:00
rick 28a29f49f2 Gollum::Wiki#add_to_tree_map updates pages if a file with the matching name + extension exists 2010-08-16 17:37:53 -07:00
Tom Preston-Werner acdb04ba4e Handle duplicate page error in frontend. Closes #10. 2010-08-16 16:54:01 -07:00
rick dd30a7bdc2 fix markup on framed absolute image urls 2010-08-16 15:49:47 -07:00
rick c7e172f5ca can't access trees as files 2010-08-16 14:57:39 -07:00
rick c69a5f80dd prevent Gollum::Wiki instances from creating new pages that overwrite pages with the same name. 2010-08-16 07:56:46 -07:00
rick ee04dd84aa normalize commit hashes so they at least show 'anonymous' if no git user is set. 2010-08-16 07:36:32 -07:00
Tom Preston-Werner 763387979a Update history for op4g/1.9_compat. 2010-08-15 11:54:02 -07:00
Chris Hoffman 4e3b4e23da Ruby 1.9 compatibility
* Adds current directory to load path for tests because 1.9 does not
* Aliases String#lines to String#to_a under 1.8 to match 1.9 behavior
* Sets encoding magic comment in test file with characters outside ascii
* Require 'ostruct' explicitly

This depends on a patch to Grit to have full functionality through the
whole stack.
2010-08-14 21:37:00 +00:00
Tom Preston-Werner 8b0c971552 Merge remote branch 'dblugeon/correct_url_markup' 2010-08-14 11:34:18 -07:00
Tom Preston-Werner f4069f1dfb Update history for rgrove/newer-sanitize. 2010-08-14 11:17:41 -07:00
Tom Preston-Werner 3d730295b3 Merge remote branch 'rgrove/newer-sanitize' 2010-08-14 10:57:09 -07:00
rick edcfdfa402 return nil for bad file version 2010-08-13 16:11:37 -07:00
dblugeon 45446f3481 update the source code url of github markup 2010-08-13 18:23:57 +02:00
Ryan Grove f159c54dc8 Increase minimum Sanitize version requirement to 1.1.0.
1.0.x versions of Sanitize require Hpricot instead of Nokogiri
and have bugs that may allow non-whitelisted HTML to sneak
through.
2010-08-12 14:18:43 -07:00
28 changed files with 1030 additions and 320 deletions
+31 -1
View File
@@ -1,6 +1,36 @@
# 1.1.0 / 2010-10-28
* Major Enhancements
* Optimize page write/update/delete to use Grit::Index::read_tree instead
of manually recreating entire index contents.
* Added --irb option for the gollum command.
* Update working dir (if present) when edited via the API (#6)
* Add basic `git grep` based search for repos.
* Minor Enhancements
* Support a `:gollum_path` Sinatra setting for `Precious::App`
* Add Wiki#size to efficiently count pages without loading them.
* Add the correct content type when serving files from the frontend.
* Add --host option and default it to 127.0.0.1.
* Allow anchors in page links, such as `[[Abc#header]]`.
* All pages retrieved with a SHA add `rel="nofollow"` to all
page links.
* Bug Fixes
* Increase minimum Sanitize version requirement to 1.1.0.
1.0.x versions of Sanitize require Hpricot instead of Nokogiri
and have bugs that may allow non-whitelisted HTML to sneak
through.
* Introduce Ruby 1.9 compatibility fixes.
* Commit hashes are normalized so that missing author data is replaced with
anonymous info.
* Prevent `Gollum::Wiki#write_page` from clobbering existing pages.
* Handle duplicate page errors in frontend.
* Fix bugs trying to retrieve pages with invalid names.
* CGI escape page names in links and redirects.
# 1.0.1 / 2010-08-12
* Force Grit dep to 2.1 or higher.
* Bug Fixes
* Force Grit dep to 2.1 or higher.
# 1.0.0 / 2010-08-12
+2 -2
View File
@@ -63,7 +63,7 @@ choose. Special footers can be created in `footer files`. Other content
## PAGE FILES
Page files may be written in any format supported by
[GitHub-Markup](http://github.com/defunkt/github-markup) (except roff). The
[GitHub-Markup](http://github.com/github/markup) (except roff). The
current list of formats and allowed extensions is:
* ASCIIDoc: .asciidoc
@@ -326,7 +326,7 @@ Initialize the Gollum::Repo object:
wiki = Gollum::Wiki.new("my-gollum-repo.git")
# => <Gollum::Wiki>
By default, internal wiki links are all absolute from the root. To specify a different base path, you can send specify the `:base_path` option:
By default, internal wiki links are all absolute from the root. To specify a different base path, you can specify the `:base_path` option:
wiki = Gollum::Wiki.new("my-gollum-repo.git", :base_path => "/wiki")
+2 -2
View File
@@ -47,7 +47,7 @@ task :default => :test
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test'
test.libs << 'lib' << 'test' << '.'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
end
@@ -143,4 +143,4 @@ task :validate do
puts "A `VERSION` file at root level violates Gem best practices."
exit!
end
end
end
+69 -7
View File
@@ -8,18 +8,17 @@ Gollum is a multi-format Wiki Engine/API/Frontend.
Basic Command Line Usage:
gollum [OPTIONS] [PATH]
PATH The path to the Gollum repository.
PATH The path to the Gollum repository (default .).
Options:
HELP
require 'optparse'
require 'rubygems'
require 'gollum/frontend/app'
require 'gollum'
exec = {}
options = {}
options = { 'port' => 4567, 'bind' => '127.0.0.1' }
opts = OptionParser.new do |opts|
opts.banner = help
@@ -27,15 +26,78 @@ opts = OptionParser.new do |opts|
options['port'] = port.to_i
end
opts.on("--host [HOST]", "Hostname or IP address to listen on (default 0.0.0.0).") do |host|
options['bind'] = host
end
opts.on("--version", "Display current version.") do
puts "Gollum " + Gollum::VERSION
exit 0
end
opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do
options['irb'] = true
end
end
# Read command line options into `options` hash
opts.parse!
begin
opts.parse!
rescue OptionParser::InvalidOption
puts "gollum: #{$!.message}"
puts "gollum: try 'gollum --help' for more information"
exit
end
$path = ARGV[0] || Dir.pwd
gollum_path = ARGV[0] || Dir.pwd
Precious::App.run!(options)
if options['irb']
require 'irb'
# http://jameskilton.com/2009/04/02/embedding-irb-into-your-ruby-application/
module IRB # :nodoc:
def self.start_session(binding)
unless @__initialized
args = ARGV
ARGV.replace(ARGV.dup)
IRB.setup(nil)
ARGV.replace(args)
@__initialized = true
end
ws = WorkSpace.new(binding)
irb = Irb.new(ws)
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context
catch(:IRB_EXIT) do
irb.eval_input
end
end
end
begin
wiki = Gollum::Wiki.new(gollum_path)
if !wiki.exist? then raise Grit::InvalidGitRepositoryError end
puts "Loaded Gollum wiki at #{File.expand_path(gollum_path).inspect}."
puts
puts %( page = wiki.page('page-name'))
puts %( # => <Gollum::Page>)
puts
puts %( page.raw_data)
puts %( # => "# My wiki page")
puts
puts %( page.formatted_data)
puts %( # => "<h1>My wiki page</h1>")
puts
puts "Check out the Gollum README for more."
IRB.start_session(binding)
rescue Grit::InvalidGitRepositoryError, Grit::NoSuchPathError
puts "Invalid Gollum wiki at #{File.expand_path(gollum_path).inspect}"
exit 0
end
else
require 'gollum/frontend/app'
Precious::App.set(:gollum_path, gollum_path)
Precious::App.run!(options)
end
+14 -6
View File
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
s.rubygems_version = '1.3.5'
s.name = 'gollum'
s.version = '1.0.1'
s.date = '2010-08-12'
s.version = '1.1.0'
s.date = '2010-10-28'
s.rubyforge_project = 'gollum'
s.summary = "A simple, Git-powered wiki."
@@ -23,17 +23,19 @@ Gem::Specification.new do |s|
s.rdoc_options = ["--charset=UTF-8"]
s.extra_rdoc_files = %w[README.md LICENSE]
s.add_dependency('grit', "~> 2.1")
s.add_dependency('grit', "~> 2.3")
s.add_dependency('github-markup', [">= 0.4.0", "< 1.0.0"])
s.add_dependency('albino', "~> 1.0")
s.add_dependency('sinatra', "~> 1.0")
s.add_dependency('mustache', [">= 0.11.2", "< 1.0.0"])
s.add_dependency('sanitize', "~> 1.0")
s.add_dependency('sanitize', "~> 1.1")
s.add_dependency('nokogiri', "~> 1.4")
s.add_development_dependency('shoulda')
s.add_development_dependency('RedCloth')
s.add_development_dependency('mocha')
s.add_development_dependency('org-ruby')
s.add_development_dependency('rdiscount')
s.add_development_dependency('shoulda')
# = MANIFEST =
s.files = %w[
@@ -46,6 +48,7 @@ Gem::Specification.new do |s|
gollum.gemspec
lib/gollum.rb
lib/gollum/albino.rb
lib/gollum/blob_entry.rb
lib/gollum/file.rb
lib/gollum/frontend/app.rb
lib/gollum/frontend/public/css/editbar.css
@@ -443,19 +446,24 @@ Gem::Specification.new do |s|
lib/gollum/frontend/templates/create.mustache
lib/gollum/frontend/templates/edit.mustache
lib/gollum/frontend/templates/editbar.mustache
lib/gollum/frontend/templates/error.mustache
lib/gollum/frontend/templates/history.mustache
lib/gollum/frontend/templates/layout.mustache
lib/gollum/frontend/templates/page.mustache
lib/gollum/frontend/templates/search.mustache
lib/gollum/frontend/views/compare.rb
lib/gollum/frontend/views/create.rb
lib/gollum/frontend/views/edit.rb
lib/gollum/frontend/views/editable.rb
lib/gollum/frontend/views/error.rb
lib/gollum/frontend/views/history.rb
lib/gollum/frontend/views/layout.rb
lib/gollum/frontend/views/page.rb
lib/gollum/frontend/views/search.rb
lib/gollum/markup.rb
lib/gollum/page.rb
lib/gollum/pagination.rb
lib/gollum/ruby1.8.rb
lib/gollum/wiki.rb
templates/formatting.html
test/examples/lotr.git/HEAD
@@ -503,4 +511,4 @@ Gem::Specification.new do |s|
# = MANIFEST =
s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
end
end
+25 -1
View File
@@ -1,13 +1,18 @@
# stdlib
require 'digest/md5'
require 'ostruct'
# external
require 'grit'
require 'github/markup'
require 'sanitize'
# ruby 1.8 compatibility
require 'gollum/ruby1.8'
# internal
require 'gollum/pagination'
require 'gollum/blob_entry'
require 'gollum/wiki'
require 'gollum/page'
require 'gollum/file'
@@ -15,7 +20,7 @@ require 'gollum/markup'
require 'gollum/albino'
module Gollum
VERSION = '1.0.1'
VERSION = '1.1.0'
SANITIZATION_OPTIONS = {
:elements => [
@@ -54,5 +59,24 @@ module Gollum
'img' => {'href' => ['http', 'https', :relative]}
}
}
HISTORY_SANITIZATION_OPTIONS = SANITIZATION_OPTIONS.merge(
:add_attributes => {
'a' => {'rel' => 'nofollow'}
}
)
class Error < StandardError; end
class DuplicatePageError < Error
attr_accessor :dir
attr_accessor :existing_path
attr_accessor :attempted_path
def initialize(dir, existing, attempted, message = nil)
@dir = dir
@existing_path = existing
@attempted_path = attempted
super(message || "Cannot write #{@dir}/#{@attempted_path}, found #{@dir}/#{@existing_path}.")
end
end
end
+71
View File
@@ -0,0 +1,71 @@
module Gollum
class BlobEntry
# Gets the String SHA for this blob.
attr_reader :sha
# Gets the String full path for this blob.
attr_reader :path
def initialize(sha, path)
@sha = sha
@path = path
@dir = @name = @blob = nil
end
# Gets the normalized directory path for this blob.
def dir
@dir ||= self.class.normalize_dir(::File.dirname(@path))
end
# Gets the String file base name for this blob.
def name
@name ||= ::File.basename(@path)
end
# Gets a Grit::Blob instance for this blob.
#
# repo - Grit::Repo instance for the Grit::Blob.
#
# Returns an unbaked Grit::Blob instance.
def blob(repo)
@blob ||= Grit::Blob.create(repo, :id => @sha, :name => @name)
end
# Gets a Page instance for this blob.
#
# wiki - Gollum::Wiki instance for the Gollum::Page
#
# Returns a Gollum::Page instance.
def page(wiki, commit)
blob = self.blob(wiki.repo)
page = wiki.page_class.new(wiki).populate(blob, self.dir)
page.version = commit
page
end
def inspect
%(#<Gollum::BlobEntry #{@sha} #{@path}>)
end
# Normalizes a given directory name for searching through tree paths.
# Ensures that a directory begins with a slash, or
#
# normalize_dir("") # => ""
# normalize_dir(".") # => ""
# normalize_dir("foo") # => "/foo"
# normalize_dir("/foo/") # => "/foo"
# normalize_dir("/") # => ""
#
# dir - String directory name.
#
# Returns a normalized String directory name, or nil if no directory
# is given.
def self.normalize_dir(dir)
if dir
dir = ::File.expand_path(dir, '/')
dir = '' if dir == '/'
end
dir
end
end
end
+11 -6
View File
@@ -33,6 +33,11 @@ module Gollum
# Public: The String path of the file.
attr_reader :path
# Public: The String mime type of the file.
def mime_type
@blob.mime_type
end
#########################################################################
#
# Internal Methods
@@ -46,14 +51,14 @@ module Gollum
#
# Returns a Gollum::File or nil if the file could not be found.
def find(name, version)
commit = @wiki.repo.commit(version)
if blob = commit.tree / name
@blob = blob
checked = name.downcase
map = @wiki.tree_map_for(version)
sha = @wiki.ref_map[version] || version
if entry = map.detect { |entry| entry.path.downcase == checked }
@path = name
@version = commit
@blob = Grit::Blob.create(@wiki.repo, :id => entry.sha, :name => entry.name)
@version = Grit::Commit.create(@wiki.repo, :id => sha)
self
else
nil
end
end
end
+34 -24
View File
@@ -1,3 +1,4 @@
require 'cgi'
require 'sinatra'
require 'gollum'
require 'mustache/sinatra'
@@ -12,6 +13,7 @@ module Precious
dir = File.dirname(File.expand_path(__FILE__))
# We want to serve public assets for now
set :public, "#{dir}/public"
set :static, true
@@ -38,9 +40,9 @@ module Precious
show_page_or_file('Home')
end
get '/edit/:name' do
@name = params[:name]
wiki = Gollum::Wiki.new($path)
get '/edit/*' do
@name = params[:splat].first
wiki = Gollum::Wiki.new(settings.gollum_path)
if page = wiki.page(@name)
@page = page
@content = page.raw_data
@@ -50,38 +52,43 @@ module Precious
end
end
post '/edit/:name' do
name = params[:name]
wiki = Gollum::Wiki.new($path)
post '/edit/*' do
name = params[:splat].first
wiki = Gollum::Wiki.new(settings.gollum_path)
page = wiki.page(name)
format = params[:format].intern
name = params[:rename] if params[:rename]
wiki.update_page(page, name, format, params[:content], commit_message)
redirect "/#{Gollum::Page.cname name}"
redirect "/#{CGI.escape(Gollum::Page.cname(name))}"
end
post '/create/:name' do
post '/create/*' do
name = params[:page]
wiki = Gollum::Wiki.new($path)
wiki = Gollum::Wiki.new(settings.gollum_path)
format = params[:format].intern
wiki.write_page(name, format, params[:content], commit_message)
redirect "/#{name}"
begin
wiki.write_page(name, format, params[:content], commit_message)
redirect "/#{CGI.escape(name)}"
rescue Gollum::DuplicatePageError => e
@message = "Duplicate page: #{e.message}"
mustache :error
end
end
post '/preview' do
format = params['wiki_format']
data = params['text']
wiki = Gollum::Wiki.new($path)
wiki = Gollum::Wiki.new(settings.gollum_path)
wiki.preview_page("Preview", data, format).formatted_data
end
get '/history/:name' do
@name = params[:name]
wiki = Gollum::Wiki.new($path)
wiki = Gollum::Wiki.new(settings.gollum_path)
@page = wiki.page(@name)
@page_num = [params[:page].to_i, 1].max
@versions = @page.versions :page => @page_num
@@ -91,10 +98,10 @@ module Precious
post '/compare/:name' do
@versions = params[:versions] || []
if @versions.size < 2
redirect "/history/#{params[:name]}"
redirect "/history/#{CGI.escape(params[:name])}"
else
redirect "/compare/%s/%s...%s" % [
params[:name],
CGI.escape(params[:name]),
@versions.last,
@versions.first]
end
@@ -103,7 +110,7 @@ module Precious
get '/compare/:name/:version_list' do
@name = params[:name]
@versions = params[:version_list].split(/\.{2,3}/)
wiki = Gollum::Wiki.new($path)
wiki = Gollum::Wiki.new(settings.gollum_path)
@page = wiki.page(@name)
diffs = wiki.repo.diff(@versions.first, @versions.last, @page.path)
@diff = diffs.first
@@ -112,7 +119,7 @@ module Precious
get %r{/(.+?)/([0-9a-f]{40})} do
name = params[:captures][0]
wiki = Gollum::Wiki.new($path)
wiki = Gollum::Wiki.new(settings.gollum_path)
if page = wiki.page(name, params[:captures][1])
@page = page
@name = name
@@ -123,18 +130,26 @@ module Precious
end
end
get '/search' do
@query = params[:q]
wiki = Gollum::Wiki.new(settings.gollum_path)
@results = wiki.search @query
mustache :search
end
get '/*' do
show_page_or_file(params[:splat].first)
end
def show_page_or_file(name)
wiki = Gollum::Wiki.new($path)
wiki = Gollum::Wiki.new(settings.gollum_path)
if page = wiki.page(name)
@page = page
@name = name
@content = page.formatted_data
mustache :page
elsif file = wiki.file(name)
content_type file.mime_type
file.raw_data
else
@name = name
@@ -143,12 +158,7 @@ module Precious
end
def commit_message
message = params[:message]
author_name = `git config --get user.name`.strip || 'Anonymous'
author_email = `git config --get user.email`.strip || 'anon@anon.com'
{ :message => message,
:name => author_name,
:email => author_email }
{ :message => params[:message] }
end
end
end
@@ -1,7 +1,7 @@
<div class="guide">
<div class="main">
<div class="actions">
<a href="/{{name}}">&laquo; Back</a>
<a href="/{{escaped_name}}">&laquo; Back</a>
</div>
<h1>{{title}}: {{before}} &rarr; {{after}}</h1>
<div id="files">
@@ -2,7 +2,7 @@
<a href="/">&laquo; Home</a>
<h1>{{title}}</h1>
<form class="new_wiki" method="post" action="/create/{{name}}">
<form class="new_wiki" method="post" action="/create/{{escaped_name}}">
<div>
<label>
Title<br />
+2 -2
View File
@@ -1,8 +1,8 @@
<div class="write">
<a href="/{{name}}">&laquo; Back</a>
<a href="/{{escaped_name}}">&laquo; Back</a>
<h1>{{title}}</h1>
<form class="edit_wiki" method="post" action="/edit/{{name}}">
<form class="edit_wiki" method="post" action="/edit/{{escaped_name}}">
<div>
<label>
Title<br />
@@ -0,0 +1,11 @@
<div class="guide">
<div class="main">
<div class="actions">
<a href="/">Home</a>
</div>
<h1>Error</h1>
<div class="error">
{{message}}
</div>
</div>
</div>
@@ -1,10 +1,10 @@
<div class="guide">
<div class="main">
<div class="actions">
<a href="/{{name}}">&laquo; Back</a>
<a href="/{{escaped_name}}">&laquo; Back</a>
</div>
<h1>{{title}}</h1>
<form id="history" method="post" action="/compare/{{name}}">
<form id="history" method="post" action="/compare/{{escaped_name}}">
<table class="commits" cellpadding="0" cellspacing="0">
<tr>
<th colspan="5">
@@ -17,7 +17,7 @@
<input name="versions[]" type="checkbox" value="{{id}}" />
</td>
<td class="sha">
<a href="/{{name}}/{{id}}">{{id7}}</a>
<a href="/{{escaped_name}}/{{id}}">{{id7}}</a>
</td>
<td nowrap class="author">
<img src="http://www.gravatar.com/avatar/{{gravatar}}?s=16" alt="Gravatar" />
+9 -3
View File
@@ -1,7 +1,13 @@
<div class="guide">
<div class="main">
<div class="actions">
<a href="/">Home</a> | <a href="/edit/{{name}}">Edit</a>
<form action="/search" method="get">
<div>
<a href="/">Home</a> |
<a href="/edit/{{escaped_name}}">Edit</a> |
<input type="search" name="q" size="10" /> <input type="submit" value="search" />
</div>
</form>
</div>
<h1>{{title}}</h1>
<div class="content wikistyle gollum {{format}}">
@@ -18,10 +24,10 @@
<div style="float: left;">
<small>Last edited by <b>{{author}}</b>, {{date}}</small>
<div class="actions">
<a href="/">Home</a> | <a href="/edit/{{name}}">Edit</a>
<a href="/">Home</a> | <a href="/edit/{{escaped_name}}">Edit</a>
</div>
</div>
<div style="float: right;">
<a href="/history/{{name}}">View Revision History</a>
<a href="/history/{{escaped_name}}">View Revision History</a>
</div>
</div>
@@ -0,0 +1,19 @@
<div class="guide">
<div class="main">
<div class="actions">
<form action="/search" method="get">
<a href="/">Home</a> | <input type="search" name="q" size="10" /> <input type="submit" value="search" />
</form>
</div>
<h1>Search for “{{query}}”</h1>
<div class="content wikistyle gollum">
{{#has_results}}
<ul>
{{#results}}
<li><a href="/{{name}}">{{name}} ({{count}})</a></li>
{{/results}}
</ul>
{{/has_results}}
</div>
</div>
</div>
+7
View File
@@ -0,0 +1,7 @@
module Precious
module Views
class Error < Layout
attr_reader :message
end
end
end
+6
View File
@@ -1,3 +1,5 @@
require 'cgi'
module Precious
module Views
class Layout < Mustache
@@ -6,6 +8,10 @@ module Precious
attr_reader :name
def escaped_name
CGI.escape(@name)
end
def title
"Home"
end
+12
View File
@@ -0,0 +1,12 @@
module Precious
module Views
class Search < Layout
attr_reader :content, :page, :footer, :results, :query
def has_results
!@results.empty?
end
end
end
end
+73 -29
View File
@@ -1,4 +1,5 @@
require 'digest/sha1'
require 'cgi'
module Gollum
class Markup
@@ -21,8 +22,14 @@ module Gollum
# Render the content with Gollum wiki syntax on top of the file's own
# markup language.
#
# no_follow - Boolean that determines if rel="nofollow" is added to all
# <a> tags.
#
# Returns the formatted String content.
def render
def render(no_follow = false)
sanitize_options = no_follow ?
HISTORY_SANITIZATION_OPTIONS :
SANITIZATION_OPTIONS
data = extract_tex(@data)
data = extract_code(data)
data = extract_tags(data)
@@ -36,9 +43,9 @@ module Gollum
end
data = process_tags(data)
data = process_code(data)
data = Sanitize.clean(data, SANITIZATION_OPTIONS)
data = Sanitize.clean(data, sanitize_options)
data = process_tex(data)
data = data.gsub(/<p><\/p>/, '')
data.gsub!(/<p><\/p>/, '')
data
end
@@ -114,28 +121,33 @@ module Gollum
# Process all tags from the tagmap and replace the placeholders with the
# final markup.
#
# data - The String data (with placeholders).
# data - The String data (with placeholders).
# no_follow - Boolean that determines if rel="nofollow" is added to all
# <a> tags.
#
# Returns the marked up String data.
def process_tags(data)
def process_tags(data, no_follow = false)
@tagmap.each do |id, tag|
data.gsub!(id, process_tag(tag))
data.gsub!(id, process_tag(tag, no_follow))
end
data
end
# Process a single tag into its final HTML form.
#
# tag - The String tag contents (the stuff inside the double brackets).
# tag - The String tag contents (the stuff inside the double
# brackets).
# no_follow - Boolean that determines if rel="nofollow" is added to all
# <a> tags.
#
# Returns the String HTML version of the tag.
def process_tag(tag)
def process_tag(tag, no_follow = false)
if html = process_image_tag(tag)
return html
elsif html = process_file_link_tag(tag)
return html
html
elsif html = process_file_link_tag(tag, no_follow)
html
else
return process_page_link_tag(tag)
process_page_link_tag(tag, no_follow)
end
end
@@ -150,7 +162,7 @@ module Gollum
name = parts[0].strip
path = if file = find_file(name)
::File.join @wiki.base_path, file.path
elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/
elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i
name
end
@@ -200,7 +212,7 @@ module Gollum
classes << 'frame' if opts['frame']
%{<span class="#{classes.join(' ')}">} +
%{<span>} +
%{<img src="/#{file.path}" #{attr_string}/>} +
%{<img src="#{path}" #{attr_string}/>} +
(alt ? %{<span>#{alt}</span>} : '') +
%{</span>} +
%{</span>}
@@ -228,11 +240,14 @@ module Gollum
# Attempt to process the tag as a file link tag.
#
# tag - The String tag contents (the stuff inside the double brackets).
# tag - The String tag contents (the stuff inside the double
# brackets).
# no_follow - Boolean that determines if rel="nofollow" is added to all
# <a> tags.
#
# Returns the String HTML if the tag is a valid file link tag or nil
# if it is not.
def process_file_link_tag(tag)
def process_file_link_tag(tag, no_follow = false)
parts = tag.split('|')
name = parts[0].strip
path = parts[1] && parts[1].strip
@@ -244,37 +259,49 @@ module Gollum
nil
end
if name && path && file
tag = if name && path && file
%{<a href="#{::File.join @wiki.base_path, file.path}">#{name}</a>}
elsif name && path
%{<a href="#{path}">#{name}</a>}
else
nil
end
if tag && no_follow
tag.sub! /^<a/, '<a ref="nofollow"'
end
tag
end
# Attempt to process the tag as a page link tag.
#
# tag - The String tag contents (the stuff inside the double brackets).
# tag - The String tag contents (the stuff inside the double
# brackets).
# no_follow - Boolean that determines if rel="nofollow" is added to all
# <a> tags.
#
# Returns the String HTML if the tag is a valid page link tag or nil
# if it is not.
def process_page_link_tag(tag)
def process_page_link_tag(tag, no_follow = false)
parts = tag.split('|')
name = parts[0].strip
cname = Page.cname((parts[1] || parts[0]).strip)
if name =~ %r{^https?://} && parts[1].nil?
tag = if name =~ %r{^https?://} && parts[1].nil?
%{<a href="#{name}">#{name}</a>}
else
if page = @wiki.page(cname)
link = ::File.join(@wiki.base_path, Page.cname(page.name))
presence = "present"
else
link = ::File.join(@wiki.base_path, cname)
presence = "absent"
presence = "absent"
link_name = cname
page, extra = find_page_from_name(cname)
if page
link_name = Page.cname(page.name)
presence = "present"
end
%{<a class="internal #{presence}" href="#{link}">#{name}</a>}
link = ::File.join(@wiki.base_path, CGI.escape(link_name))
%{<a class="internal #{presence}" href="#{link}#{extra}">#{name}</a>}
end
if tag && no_follow
tag.sub! /^<a/, '<a ref="nofollow"'
end
tag
end
# Find the given file in the repo.
@@ -291,6 +318,23 @@ module Gollum
end
end
# Find a page from a given cname. If the page has an anchor (#) and has
# no match, strip the anchor and try again.
#
# cname - The String canonical page name.
#
# Returns a Gollum::Page instance if a page is found, or an Array of
# [Gollum::Page, String extra] if a page without the extra anchor data
# is found.
def find_page_from_name(cname)
if page = @wiki.page(cname)
return page
end
if pos = cname.index('#')
[@wiki.page(cname[0...pos]), cname[pos..-1]]
end
end
#########################################################################
#
# Code
@@ -320,7 +364,7 @@ module Gollum
@codemap.each do |id, spec|
lang = spec[:lang]
code = spec[:code]
if code.all? { |line| line =~ /\A\r?\n\Z/ || line =~ /^( |\t)/ }
if code.lines.all? { |line| line =~ /\A\r?\n\Z/ || line =~ /^( |\t)/ }
code.gsub!(/^( |\t)/m, '')
end
data.gsub!(id, Gollum::Albino.new(code, lang).colorize)
@@ -328,4 +372,4 @@ module Gollum
data
end
end
end
end
+49 -56
View File
@@ -14,6 +14,11 @@ module Gollum
:asciidoc => "AsciiDoc",
:pod => "Pod" }
# Sets a Boolean determing whether this page is a historical version.
#
# Returns nothing.
attr_writer :historical
# Checks if a filename has a valid extension understood by GitHub::Markup.
#
# filename - String filename, like "Home.md".
@@ -35,6 +40,14 @@ module Gollum
filename =~ /^_/ ? false : match
end
# Reusable filter to turn a filename (without path) into a canonical name.
# Strips extension, converts spaces to dashes.
#
# Returns the filtered String.
def self.canonicalize_filename(filename)
filename.split('.')[0..-2].join('.').gsub('-', ' ')
end
# Public: Initialize a page.
#
# wiki - The Gollum::Wiki in question.
@@ -57,7 +70,7 @@ module Gollum
#
# Returns the String name.
def name
filename.split('.')[0..-2].join('.').gsub('-', ' ')
self.class.canonicalize_filename(filename)
end
# Public: If the first element of a formatted page is an <h1> tag it can
@@ -107,7 +120,7 @@ module Gollum
#
# Returns the String data.
def formatted_data
@blob && Gollum::Markup.new(self).render
@blob && Gollum::Markup.new(self).render(historical?)
end
# Public: The format of the page.
@@ -174,20 +187,24 @@ module Gollum
dirs = self.path.split('/')
dirs.pop
map = @wiki.tree_map_for(self.version.id)
while !dirs.empty?
tree = self.version.tree / dirs.join('/')
if page = find_page_in_this_tree(tree, dirs.join('/'), '_Footer')
if page = find_page_in_tree(map, '_Footer', dirs.join('/'))
return page
end
dirs.pop
end
tree = self.version.tree
if page = find_page_in_this_tree(tree, '', '_Footer')
return page
end
find_page_in_tree(map, '_Footer', '')
end
return nil
# Gets a Boolean determining whether this page is a historical version.
# Historical pages are pulled using exact SHA hashes and format all links
# with rel="nofollow"
#
# Returns true if the page is pulled from a named branch or tag, or false.
def historical?
!!@historical
end
#########################################################################
@@ -207,7 +224,9 @@ module Gollum
#
# Returns the String canonical name.
def self.cname(name)
name.gsub(%r{[ /<>]}, '-')
name.respond_to?(:gsub) ?
name.gsub(%r{[ /<>]}, '-') :
''
end
# Convert a format Symbol into an extension String.
@@ -251,61 +270,35 @@ module Gollum
#
# Returns a Gollum::Page or nil if the page could not be found.
def find(name, version)
if commit = @wiki.repo.commit(version)
if page = find_page_in_tree(commit.tree, name)
page.version = commit
page
end
map = @wiki.tree_map_for(version)
if page = find_page_in_tree(map, name)
sha = @wiki.ref_map[version] || version
page.version = Grit::Commit.create(@wiki.repo, :id => sha)
page.historical = sha == version
page
end
rescue Grit::GitRuby::Repository::NoSuchShaFound
end
# Find a page in a given tree.
#
# tree - The Grit::Tree in which to look.
# name - The canonical String page name.
# map - The Array tree map from Wiki#tree_map.
# name - The canonical String page name.
# checked_dir - Optional String of the directory a matching page needs
# to be in. The string should
#
# Returns a Gollum::Page or nil if the page could not be found.
def find_page_in_tree(tree, name)
treemap = {}
trees = [tree]
while !trees.empty?
ptree = trees.shift
ptree.contents.each do |item|
case item
when Grit::Blob
if page_match(name, item.name)
return self.class.new(@wiki).populate(item, tree_path(treemap, ptree))
end
when Grit::Tree
treemap[item] = ptree
trees << item
end
end
def find_page_in_tree(map, name, checked_dir = nil)
return nil if name.to_s.empty?
if checked_dir = BlobEntry.normalize_dir(checked_dir)
checked_dir.downcase!
end
return nil # nothing was found
end
# Find a page in a given tree without recursing into subtrees.
#
# tree - The Grit::Tree in which to look.
# dir - The String path of the given Grit::Tree.
# name - The canonical String page name.
#
# Returns a Gollum::Page or nil if the page could not be found.
def find_page_in_this_tree(tree, dir, name)
treemap = {}
tree.contents.each do |item|
case item
when Grit::Blob
if page_match(name, item.name)
path = dir == '' ? '' : ::File.join('/', dir)
page = self.class.new(@wiki).populate(item, path)
page.version = self.version
return page
end
end
map.each do |entry|
next if entry.name.to_s.empty?
next unless checked_dir.nil? || entry.dir.downcase == checked_dir
next unless page_match(name, entry.name)
return entry.page(@wiki, @version)
end
return nil # nothing was found
+3
View File
@@ -0,0 +1,3 @@
class String
alias :lines :to_a if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
end
+314 -101
View File
@@ -9,6 +9,12 @@ module Gollum
# Sets the file class used by all instances of this Wiki.
attr_writer :file_class
# Sets the default name for commits.
attr_accessor :default_committer_name
# Sets the default email for commits.
attr_accessor :default_committer_email
# Gets the page class used by all instances of this Wiki.
# Default: Gollum::Page.
def page_class
@@ -32,6 +38,8 @@ module Gollum
end
end
self.default_committer_name = 'Anonymous'
self.default_committer_email = 'anon@anon.com'
# The String base path to prefix to internal links. For example, when set
# to "/wiki", the page "Hobbit" will be linked as "/wiki/Hobbit". Defaults
@@ -43,7 +51,7 @@ module Gollum
# repo - The String path to the Git repository that holds the Gollum
# site.
# options - Optional Hash:
# :base_path - String base path for all Wiki links.
# :base_path - String base path for all Wiki links.
# Default: "/"
# :page_class - The page Class. Default: Gollum::Page
# :file_class - The file Class. Default: Gollum::File
@@ -55,6 +63,7 @@ module Gollum
@base_path = options[:base_path] || "/"
@page_class = options[:page_class] || self.class.page_class
@file_class = options[:file_class] || self.class.file_class
clear_cache
end
# Public: check whether the wiki's git repo exists on the filesystem.
@@ -115,17 +124,23 @@ module Gollum
#
# Returns the String SHA1 of the newly written version.
def write_page(name, format, data, commit = {})
map = {}
commit = normalize_commit(commit)
index = self.repo.index
if pcommit = @repo.commit('master')
map = tree_map(pcommit.tree)
index.read_tree(pcommit.tree.id)
end
map = add_to_tree_map(map, '', name, format, data)
index = tree_map_to_index(map)
add_to_index(index, '', name, format, data)
parents = pcommit ? [pcommit] : []
actor = Grit::Actor.new(commit[:name], commit[:email])
index.commit(commit[:message], parents, actor)
sha1 = index.commit(commit[:message], parents, actor)
@ref_map.clear
update_working_dir(index, '', name, format)
sha1
end
# Public: Update an existing page with new content. The location of the
@@ -144,24 +159,32 @@ module Gollum
#
# Returns the String SHA1 of the newly written version.
def update_page(page, name, format, data, commit = {})
commit = normalize_commit(commit)
pcommit = @repo.commit('master')
map = tree_map(pcommit.tree)
name ||= page.name
format ||= page.format
index = nil
index = self.repo.index
dir = ::File.dirname(page.path)
dir = '' if dir == '.'
index.read_tree(pcommit.tree.id)
if page.name == name && page.format == format
index = tree_map_to_index(map)
index.add(page.path, normalize(data))
else
map = delete_from_tree_map(map, page.path)
dir = ::File.dirname(page.path)
map = add_to_tree_map(map, dir, name, format, data)
index = tree_map_to_index(map)
index.delete(page.path)
add_to_index(index, dir, name, format, data, :allow_same_ext)
end
actor = Grit::Actor.new(commit[:name], commit[:email])
index.commit(commit[:message], [pcommit], actor)
sha1 = index.commit(commit[:message], [pcommit], actor)
@ref_map.clear
update_working_dir(index, dir, page.name, page.format)
update_working_dir(index, dir, name, format)
sha1
end
# Public: Delete a page.
@@ -169,19 +192,27 @@ module Gollum
# page - The Gollum::Page to delete.
# commit - The commit Hash details:
# :message - The String commit message.
# :author - The String author full name.
# :name - The String author full name.
# :email - The String email address.
#
# Returns the String SHA1 of the newly written version.
def delete_page(page, commit)
pcommit = @repo.commit('master')
map = tree_map(pcommit.tree)
map = delete_from_tree_map(map, page.path)
index = tree_map_to_index(map)
index = self.repo.index
index.read_tree(pcommit.tree.id)
index.delete(page.path)
dir = ::File.dirname(page.path)
dir = '' if dir == '.'
actor = Grit::Actor.new(commit[:name], commit[:email])
index.commit(commit[:message], [pcommit], actor)
sha1 = index.commit(commit[:message], [pcommit], actor)
@ref_map.clear
update_working_dir(index, dir, page.name, page.format)
sha1
end
# Public: Lists all pages for this wiki.
@@ -190,11 +221,39 @@ module Gollum
#
# Returns an Array of Gollum::Page instances.
def pages(treeish = nil)
treeish ||= 'master'
if commit = @repo.commit(treeish)
tree_list(commit)
else
[]
tree_list(treeish || 'master')
end
# Public: Returns the number of pages accessible from a commit
#
# ref - A String ref that is either a commit SHA or references one.
#
# Returns a Fixnum
def size(ref = nil)
tree_map_for(ref || 'master').inject(0) do |num, entry|
num + (@page_class.valid_page_name?(entry.name) ? 1 : 0)
end
rescue Grit::GitRuby::Repository::NoSuchShaFound
0
end
# Public: Search all pages for this wiki.
#
# query - The string to search for
#
# Returns an Array with Objects of page name and count of matches
def search(query)
# See: http://github.com/Sirupsen/gollum/commit/f0a6f52bdaf6bee8253ca33bb3fceaeb27bfb87e
search_output = @repo.git.grep({:c => query}, 'master')
search_output.split("\n").collect do |line|
result = line.split(':')
file_name = Gollum::Page.canonicalize_filename(::File.basename(result[1]))
{
:count => result[2].to_i,
:name => file_name
}
end
end
@@ -225,6 +284,26 @@ module Gollum
# Returns the String path.
attr_reader :path
# Gets a Hash cache of refs to commit SHAs.
#
# {"master" => "abc123", ...}
#
# Returns the Hash cache.
attr_reader :ref_map
# Gets a Hash cache of commit SHAs to a recursive tree of blobs.
#
# {"abc123" => [["lib/foo.rb", "blob-sha"], [file, sha], ...], ...}
#
# Returns the Hash cache.
attr_reader :tree_map
# Gets the page class used by all instances of this Wiki.
attr_reader :page_class
# Gets the file class used by all instances of this Wiki.
attr_reader :file_class
# Normalize the data.
#
# data - The String data to be normalized.
@@ -234,102 +313,236 @@ module Gollum
data.gsub(/\r/, '')
end
# Assemble a Page's filename from its name and format.
#
# name - The String name of the page (may be in human format).
# format - The Symbol format of the page.
#
# Returns the String filename.
def page_file_name(name, format)
ext = @page_class.format_to_ext(format)
@page_class.cname(name) + '.' + ext
end
# Update the given file in the repository's working directory if there
# is a working directory present.
#
# index - The Grit::Index with which to sync.
# dir - The String directory in which the file lives.
# name - The String name of the page (may be in human format).
# format - The Symbol format of the page.
#
# Returns nothing.
def update_working_dir(index, dir, name, format)
unless @repo.bare
path =
if dir == ''
page_file_name(name, format)
else
::File.join(dir, page_file_name(name, format))
end
Dir.chdir(::File.join(@repo.path, '..')) do
if file_path_scheduled_for_deletion?(index.tree, path)
@repo.git.rm({'f' => true}, '--', path)
else
@repo.git.checkout({}, 'HEAD', '--', path)
end
end
end
end
# Fill an array with a list of pages.
#
# commit - The Grit::Commit
# tree - The Grit::Tree to start with.
# sub_tree - Optional String specifying the parent path of the Page.
# ref - A String ref that is either a commit SHA or references one.
#
# Returns a flat Array of Gollum::Page instances.
def tree_list(commit, tree = commit.tree, sub_tree = nil)
list = []
path = tree.name ? "#{sub_tree}/#{tree.name}" : ''
tree.contents.each do |item|
case item
when Grit::Blob
if @page_class.valid_page_name?(item.name)
page = @page_class.new(self).populate(item, path)
page.version = commit
list << page
end
when Grit::Tree
list.push *tree_list(commit, item, path)
end
def tree_list(ref)
tree_map_for(ref).inject([]) do |list, entry|
next list unless @page_class.valid_page_name?(entry.name)
sha = ref_map[ref]
list << entry.page(self, @repo.commit(sha))
end
list
end
# Fill an index with the existing state of the repository.
#
# tree - The Grit::Tree to start with.
#
# Returns a nested Hash of filename to content mappings.
def tree_map(tree)
map = {}
tree.contents.each do |item|
case item
when Grit::Blob
map[item.name] = item.data
when Grit::Tree
map[item.name] = tree_map(item)
end
end
map
end
# Use a treemap to fill in the index.
# Determine if a given file is scheduled to be deleted in the next commit
# for the given Index.
#
# map - The Hash map:
# key - The String directory or filename.
# val - The Hash submap or the String contents of the file.
# index - The Grit::Index to use. Leave blank when calling from outside
# this method (default: nil).
# path - The String path of the file including extension.
#
# Returns the Grit::Index.
def tree_map_to_index(map, prefix = '', index = nil)
index ||= @repo.index
map.each do |k, v|
case k
when String
name = [prefix, k].join('/')[1..-1]
index.add(k, v)
when Hash
new_prefix = [prefix, k].join('/')[1..-1]
tree_map_to_index(v, new_prefix, index)
# Returns the Boolean response.
def file_path_scheduled_for_deletion?(map, path)
parts = path.split('/')
if parts.size == 1
deletions = map.keys.select { |k| !map[k] }
deletions.any? { |d| d == parts.first }
else
part = parts.shift
if rest = map[part]
file_path_scheduled_for_deletion?(rest, parts.join('/'))
else
false
end
end
index
end
def add_to_tree_map(map, dir, name, format, data)
ext = @page_class.format_to_ext(format)
path = @page_class.cname(name) + '.' + ext
parts = dir.split('/')
container = nil
parts.each do |part|
container = map[part]
end
(container || map)[path] = normalize(data)
map
end
# Delete an entry from a tree map.
# Determine if a given page (regardless of format) is scheduled to be
# deleted in the next commit for the given Index.
#
# map - The Hash tree map of the repository.
# path - The String path of the file to delete.
# map - The Hash map:
# key - The String directory or filename.
# val - The Hash submap or the String contents of the file.
# path - The String path of the page file. This may include the format
# extension in which case it will be ignored.
#
# Returns the modified Hash tree map.
def delete_from_tree_map(map, path)
# Returns the Boolean response.
def page_path_scheduled_for_deletion?(map, path)
parts = path.split('/')
name = parts.pop
container = nil
parts.each do |part|
container = map[part]
if parts.size == 1
deletions = map.keys.select { |k| !map[k] }
downfile = parts.first.downcase.sub(/\.\w+$/, '')
deletions.any? { |d| d.downcase.sub(/\.\w+$/, '') == downfile }
else
part = parts.shift
if rest = map[part]
page_path_scheduled_for_deletion?(rest, parts.join('/'))
else
false
end
end
(container || map).delete(name)
map
end
# Adds a page to the given Index.
#
# index - The Grit::Index to which the page will be added.
# dir - The String subdirectory of the Gollum::Page without any
# prefix or suffix slashes (e.g. "foo/bar").
# name - The String Gollum::Page name.
# format - The Symbol Gollum::Page format.
# data - The String wiki data to store in the tree map.
# allow_same_ext - A Boolean determining if the tree map allows the same
# filename with the same extension.
#
# Raises Gollum::DuplicatePageError if a matching filename already exists.
# This way, pages are not inadvertently overwritten.
#
# Returns nothing (modifies the Index in place).
def add_to_index(index, dir, name, format, data, allow_same_ext = false)
path = page_file_name(name, format)
dir = '/' if dir.strip.empty?
fullpath = ::File.join(dir, path)
fullpath = fullpath[1..-1] if fullpath =~ /^\//
if index.current_tree && tree = index.current_tree / dir
downpath = path.downcase.sub(/\.\w+$/, '')
tree.blobs.each do |blob|
next if page_path_scheduled_for_deletion?(index.tree, fullpath)
file = blob.name.downcase.sub(/\.\w+$/, '')
file_ext = ::File.extname(blob.name).sub(/^\./, '')
if downpath == file && !(allow_same_ext && file_ext == ext)
raise DuplicatePageError.new(dir, blob.name, path)
end
end
end
index.add(fullpath, normalize(data))
end
# Ensures a commit hash has all the required fields for a commit.
#
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
#
# Returns the commit Hash
def normalize_commit(commit = {})
commit[:name] = default_committer_name if commit[:name].to_s.empty?
commit[:email] = default_committer_email if commit[:email].to_s.empty?
commit
end
# Gets the default name for commits.
def default_committer_name
@default_committer_name ||= \
@repo.config['user.name'] || self.class.default_committer_name
end
# Gets the default email for commits.
def default_committer_email
@default_committer_email ||= \
@repo.config['user.email'] || self.class.default_committer_email
end
# Finds a full listing of files and their blob SHA for a given ref. Each
# listing is cached based on its actual commit SHA.
#
# ref - A String ref that is either a commit SHA or references one.
#
# Returns an Array of BlobEntry instances.
def tree_map_for(ref)
sha = @ref_map[ref] || ref
@tree_map[sha] || begin
real_sha = @repo.git.rev_list({:max_count=>1}, ref)
@ref_map[ref] = real_sha if real_sha != ref
@tree_map[real_sha] ||= parse_tree_for(real_sha)
end
rescue Grit::GitRuby::Repository::NoSuchShaFound
[]
end
# Finds the full listing of files and their blob SHA for a given commit
# SHA. No caching or ref lookups are performed.
#
# sha - String commit SHA.
#
# Returns an Array of BlobEntry instances.
def parse_tree_for(sha)
tree = @repo.git.native(:ls_tree, {:r => true, :z => true}, sha)
items = []
tree.split("\0").each do |line|
items << parse_tree_line(line)
end
items
end
# Parses a line of output from the `ls-tree` command.
#
# line - A String line of output:
# "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md"
#
# Returns an Array of BlobEntry instances.
def parse_tree_line(line)
data, name = line.split("\t")
mode, type, sha = data.split(' ')
name = decode_git_path(name)
BlobEntry.new sha, name
end
# Decode octal sequences (\NNN) in tree path names.
#
# path - String path name.
#
# Returns a decoded String.
def decode_git_path(path)
if path[0] == ?" && path[-1] == ?"
path = path[1...-1]
path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
end
path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m.to_s}")) }
path
end
# Resets the ref and tree caches for this wiki.
def clear_cache
@ref_map = {}
@tree_map = {}
end
end
end
end
+7 -1
View File
@@ -18,6 +18,12 @@ def testpath(path)
File.join(TEST_DIR, path)
end
def commit_details
{ :message => "Did something at #{Time.now}",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
end
# test/spec/mini 3
# http://gist.github.com/25455
# chris@ozmm.org
@@ -26,7 +32,7 @@ def context(*args, &block)
return super unless (name = args.first) && block
require 'test/unit'
klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
def self.test(name, &block)
def self.test(name, &block)
define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
end
def self.xtest(*args) end
+9 -2
View File
@@ -11,8 +11,15 @@ context "File" do
end
test "existing file" do
file = @wiki.file("Mordor/todo.txt")
commit = @wiki.repo.commits.first
file = @wiki.file("Mordor/todo.txt")
assert_equal "[ ] Write section on Ents\n", file.raw_data
assert_equal @wiki.repo.commits.first.id, file.version.id
assert_equal 'todo.txt', file.name
assert_equal commit.id, file.version.id
assert_equal commit.author.name, file.version.author.name
end
test "accessing tree" do
assert_nil @wiki.file("Mordor")
end
end
+107 -23
View File
@@ -6,10 +6,6 @@ context "Markup" do
FileUtils.rm_rf(@path)
Grit::Repo.init_bare(@path)
@wiki = Gollum::Wiki.new(@path)
@commit = { :message => "Add stuff",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
end
teardown do
@@ -17,12 +13,18 @@ context "Markup" do
end
test "formats page from Wiki#pages" do
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", commit_details)
assert @wiki.pages[0].formatted_data
end
#########################################################################
#
# Links
#
#########################################################################
test "double page links no space" do
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", commit_details)
# "<p>a <a class=\"internal absent\" href=\"/Foo\">Foo</a><a class=\"internal absent\" href=\"/Bar\">Bar</a> b</p>"
page = @wiki.page("Bilbo Baggins")
@@ -41,7 +43,7 @@ context "Markup" do
end
test "double page links with space" do
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]] [[Bar]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]] [[Bar]] b", commit_details)
# "<p>a <a class=\"internal absent\" href=\"/Foo\">Foo</a> <a class=\"internal absent\" href=\"/Bar\">Bar</a> b</p>"
page = @wiki.page("Bilbo Baggins")
@@ -60,7 +62,7 @@ context "Markup" do
end
test "page link" do
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Bilbo Baggins]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Bilbo Baggins]] b", commit_details)
page = @wiki.page("Bilbo Baggins")
output = page.formatted_data
@@ -69,8 +71,18 @@ context "Markup" do
assert_match /\>Bilbo Baggins\</, output
end
test "adds nofollow to links on historical pages" do
sha1 = @wiki.write_page("Sauron", :markdown, "a [[b]] c", commit_details)
page = @wiki.page("Sauron")
sha2 = @wiki.update_page(page, page.name, :markdown, "c [[b]] a", commit_details)
regx = /rel="nofollow"/
assert_no_match regx, page.formatted_data
assert_match regx, @wiki.page(page.name, sha1).formatted_data
assert_match regx, @wiki.page(page.name, sha2).formatted_data
end
test "absent page link" do
@wiki.write_page("Tolkien", :markdown, "a [[J. R. R. Tolkien]]'s b", @commit)
@wiki.write_page("Tolkien", :markdown, "a [[J. R. R. Tolkien]]'s b", commit_details)
page = @wiki.page("Tolkien")
output = page.formatted_data
@@ -80,41 +92,76 @@ context "Markup" do
end
test "page link with custom base path" do
["/wiki", "/wiki/"].each do |path|
["/wiki", "/wiki/"].each_with_index do |path, i|
name = "Bilbo Baggins #{i}"
@wiki = Gollum::Wiki.new(@path, :base_path => path)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Bilbo Baggins]] b", @commit)
@wiki.write_page(name, :markdown, "a [[#{name}]] b", commit_details)
page = @wiki.page("Bilbo Baggins")
page = @wiki.page(name)
output = page.formatted_data
assert_match /class="internal present"/, output
assert_match /href="\/wiki\/Bilbo-Baggins"/, output
assert_match /\>Bilbo Baggins\</, output
assert_match /class="internal present"/, output
assert_match /href="\/wiki\/Bilbo-Baggins-\d"/, output
assert_match /\>Bilbo Baggins \d\</, output
end
end
test "page link with included #" do
@wiki.write_page("Precious #1", :markdown, "a [[Precious #1]] b", commit_details)
page = @wiki.page('Precious #1')
output = page.formatted_data
assert_match /class="internal present"/, output
assert_match /href="\/Precious-%231"/, output
end
test "page link with extra #" do
@wiki.write_page("Potato", :markdown, "a [[Potato#1]] b", commit_details)
page = @wiki.page('Potato')
output = page.formatted_data
assert_match /class="internal present"/, output
assert_match /href="\/Potato#1"/, output
end
test "external page link" do
@wiki.write_page("Bilbo Baggins", :markdown, "a [[http://example.com]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[http://example.com]] b", commit_details)
page = @wiki.page("Bilbo Baggins")
assert_equal "<p>a <a href=\"http://example.com\">http://example.com</a> b</p>", page.formatted_data
end
#########################################################################
#
# Images
#
#########################################################################
test "image with http url" do
['http', 'https'].each do |scheme|
@wiki.write_page("Bilbo Baggins", :markdown, "a [[#{scheme}://example.com/bilbo.jpg]] b", @commit)
name = "Bilbo Baggins #{scheme}"
@wiki.write_page(name, :markdown, "a [[#{scheme}://example.com/bilbo.jpg]] b", commit_details)
page = @wiki.page("Bilbo Baggins")
page = @wiki.page(name)
output = page.formatted_data
assert_equal %{<p>a <img src="#{scheme}://example.com/bilbo.jpg" /> b</p>}, output
end
end
test "image with extension in caps with http url" do
['http', 'https'].each do |scheme|
name = "Bilbo Baggins #{scheme}"
@wiki.write_page(name, :markdown, "a [[#{scheme}://example.com/bilbo.JPG]] b", commit_details)
page = @wiki.page(name)
output = page.formatted_data
assert_equal %{<p>a <img src="#{scheme}://example.com/bilbo.JPG" /> b</p>}, output
end
end
test "image with absolute path" do
@wiki = Gollum::Wiki.new(@path, :base_path => '/wiki')
index = @wiki.repo.index
index.add("alpha.jpg", "hi")
index.commit("Add alpha.jpg")
@wiki.write_page("Bilbo Baggins", :markdown, "a [[/alpha.jpg]] [[a | /alpha.jpg]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[/alpha.jpg]] [[a | /alpha.jpg]] b", commit_details)
page = @wiki.page("Bilbo Baggins")
assert_equal %{<p>a <img src="/wiki/alpha.jpg" /><a href="/wiki/alpha.jpg">a</a> b</p>}, page.formatted_data
@@ -203,17 +250,29 @@ context "Markup" do
relative_image(content, output)
end
test "absolute image with frame" do
content = "a\n\n[[http://example.com/bilbo.jpg|frame]]\n\nb"
output = "<p>a</p>\n\n<p><span class=\"frame\"><span><img src=\"http://example.com/bilbo.jpg\" /></span></span></p>\n\n<p>b</p>"
relative_image(content, output)
end
test "image with frame and alt" do
content = "a\n\n[[alpha.jpg|frame|alt=Alpha]]\n\nb"
output = "<p>a</p>\n\n<p><span class=\"frame\"><span><img src=\"/greek/alpha.jpg\" alt=\"Alpha\" /><span>Alpha</span></span></span></p>\n\n<p>b</p>"
relative_image(content, output)
end
#########################################################################
#
# File links
#
#########################################################################
test "file link with absolute path" do
index = @wiki.repo.index
index.add("alpha.jpg", "hi")
index.commit("Add alpha.jpg")
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Alpha|/alpha.jpg]] b", @commit)
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Alpha|/alpha.jpg]] b", commit_details)
page = @wiki.page("Bilbo Baggins")
output = Gollum::Markup.new(page).render
@@ -240,6 +299,12 @@ context "Markup" do
assert_equal %{<p>a <a href="http://example.com/alpha.jpg">Alpha</a> b</p>}, page.formatted_data
end
#########################################################################
#
# Code
#
#########################################################################
test "code blocks" do
content = "a\n\n```ruby\nx = 1\n```\n\nb"
output = "<p>a</p>\n\n<div class=\"highlight\"><pre>" +
@@ -288,6 +353,12 @@ context "Markup" do
compare(content, output)
end
#########################################################################
#
# Various
#
#########################################################################
test "escaped wiki link" do
content = "a '[[Foo]], b"
output = "<p>a [[Foo]], b</p>"
@@ -309,18 +380,30 @@ context "Markup" do
compare(content, output, 'org')
end
test "tex block syntax" do
#########################################################################
#
# TeX
#
#########################################################################
test "TeX block syntax" do
content = 'a \[ a^2 \] b'
output = "<p>a <script type=\"math/tex; mode=display\">a^2</script> b</p>"
compare(content, output, 'md')
end
test "tex inline syntax" do
test "TeX inline syntax" do
content = 'a \( a^2 \) b'
output = "<p>a <script type=\"math/tex\">a^2</script> b</p>"
compare(content, output, 'md')
end
#########################################################################
#
# Helpers
#
#########################################################################
def compare(content, output, ext = "md", regexes = [])
index = @wiki.repo.index
index.add("Bilbo-Baggins.#{ext}", content)
@@ -341,8 +424,9 @@ context "Markup" do
index.add("greek/Bilbo-Baggins.md", content)
index.commit("Add alpha.jpg")
@wiki.clear_cache
page = @wiki.page("Bilbo Baggins")
rendered = Gollum::Markup.new(page).render
assert_equal output, rendered
end
end
end
+7 -1
View File
@@ -1,3 +1,4 @@
# ~*~ encoding: utf-8 ~*~
require File.join(File.dirname(__FILE__), *%w[helper])
context "Page" do
@@ -109,4 +110,9 @@ context "Page" do
footer = @wiki.page("_Footer")
assert_nil footer.footer
end
end
test "cannot convert non string to human readable page title" do
assert_equal '', Gollum::Page.cname(nil)
assert_equal '', Gollum::Page.cname(3)
end
end
+131 -48
View File
@@ -35,9 +35,54 @@ context "Wiki" do
test "list pages" do
pages = @wiki.pages
assert_equal \
%w(Bilbo-Baggins.md Eye-Of-Sauron.md Home.textile My-Precious.md),
%w(Bilbo-Baggins.md Eye-Of-Sauron.md Home.textile My-Precious.md),
pages.map { |p| p.filename }.sort
end
test "counts pages" do
assert_equal 4, @wiki.size
end
test "normalizes commit hash" do
commit = {:message => 'abc'}
name = @wiki.repo.config['user.name']
email = @wiki.repo.config['user.email']
assert_equal({:message => 'abc', :name => name, :email => email},
@wiki.normalize_commit(commit.dup))
commit[:name] = 'bob'
commit[:email] = ''
assert_equal({:message => 'abc', :name => 'bob', :email => email},
@wiki.normalize_commit(commit.dup))
commit[:email] = 'foo@bar.com'
assert_equal({:message => 'abc', :name => 'bob', :email => 'foo@bar.com'},
@wiki.normalize_commit(commit.dup))
end
test "#tree_map_for caches ref and tree" do
assert @wiki.ref_map.empty?
assert @wiki.tree_map.empty?
@wiki.tree_map_for 'master'
assert_equal({"master"=>"60f12f4254f58801b9ee7db7bca5fa8aeefaa56b"}, @wiki.ref_map)
map = @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b']
assert_equal 'Bilbo-Baggins.md', map[0].path
assert_equal '', map[0].dir
assert_equal map[0].path, map[0].name
assert_equal 'Mordor/Eye-Of-Sauron.md', map[3].path
assert_equal '/Mordor', map[3].dir
assert_equal 'Eye-Of-Sauron.md', map[3].name
end
test "#tree_map_for only caches tree for commit" do
assert @wiki.tree_map.empty?
@wiki.tree_map_for '60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'
assert @wiki.ref_map.empty?
entry = @wiki.tree_map['60f12f4254f58801b9ee7db7bca5fa8aeefaa56b'][0]
assert_equal 'Bilbo-Baggins.md', entry.path
end
end
context "Wiki page previewing" do
@@ -64,48 +109,48 @@ context "Wiki page writing" do
end
test "write_page" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
@wiki.write_page("Gollum", :markdown, "# Gollum", commit)
cd = commit_details
@wiki.write_page("Gollum", :markdown, "# Gollum", cd)
assert_equal 1, @wiki.repo.commits.size
assert_equal "Gollum page", @wiki.repo.commits.first.message
assert_equal "Tom Preston-Werner", @wiki.repo.commits.first.author.name
assert_equal "tom@github.com", @wiki.repo.commits.first.author.email
assert_equal cd[:message], @wiki.repo.commits.first.message
assert_equal cd[:name], @wiki.repo.commits.first.author.name
assert_equal cd[:email], @wiki.repo.commits.first.author.email
assert @wiki.page("Gollum")
@wiki.write_page("Bilbo", :markdown, "# Bilbo", commit)
@wiki.write_page("Bilbo", :markdown, "# Bilbo", commit_details)
assert_equal 2, @wiki.repo.commits.size
assert @wiki.page("Bilbo")
assert @wiki.page("Gollum")
end
test "is not allowed to overwrite file" do
@wiki.write_page("Abc-Def", :markdown, "# Gollum", commit_details)
assert_raises Gollum::DuplicatePageError do
@wiki.write_page("ABC DEF", :textile, "# Gollum", commit_details)
end
end
test "update_page" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
@wiki.write_page("Gollum", :markdown, "# Gollum", commit)
@wiki.write_page("Gollum", :markdown, "# Gollum", commit_details)
page = @wiki.page("Gollum")
@wiki.update_page(page, page.name, :markdown, "# Gollum2", commit)
cd = commit_details
@wiki.update_page(page, page.name, :markdown, "# Gollum2", cd)
assert_equal 2, @wiki.repo.commits.size
assert_equal "# Gollum2", @wiki.page("Gollum").raw_data
assert_equal "Gollum page", @wiki.repo.commits.first.message
assert_equal "Tom Preston-Werner", @wiki.repo.commits.first.author.name
assert_equal "tom@github.com", @wiki.repo.commits.first.author.email
assert_equal cd[:message], @wiki.repo.commits.first.message
assert_equal cd[:name], @wiki.repo.commits.first.author.name
assert_equal cd[:email], @wiki.repo.commits.first.author.email
end
test "update page with format change" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
@wiki.write_page("Gollum", :markdown, "# Gollum", commit)
@wiki.write_page("Gollum", :markdown, "# Gollum", commit_details)
assert_equal :markdown, @wiki.page("Gollum").format
page = @wiki.page("Gollum")
@wiki.update_page(page, page.name, :textile, "h1. Gollum", commit)
@wiki.update_page(page, page.name, :textile, "h1. Gollum", commit_details)
assert_equal 2, @wiki.repo.commits.size
assert_equal :textile, @wiki.page("Gollum").format
@@ -113,30 +158,24 @@ context "Wiki page writing" do
end
test "update page with name change" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
@wiki.write_page("Gollum", :markdown, "# Gollum", commit)
@wiki.write_page("Gollum", :markdown, "# Gollum", commit_details)
assert_equal :markdown, @wiki.page("Gollum").format
page = @wiki.page("Gollum")
@wiki.update_page(page, 'Smeagol', :markdown, "h1. Gollum", commit)
@wiki.update_page(page, 'Smeagol', :markdown, "h1. Gollum", commit_details)
assert_equal 2, @wiki.repo.commits.size
assert_equal "h1. Gollum", @wiki.page("Smeagol").raw_data
end
test "update page with name and format change" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
@wiki.write_page("Gollum", :markdown, "# Gollum", commit)
@wiki.write_page("Gollum", :markdown, "# Gollum", commit_details)
assert_equal :markdown, @wiki.page("Gollum").format
page = @wiki.page("Gollum")
@wiki.update_page(page, 'Smeagol', :textile, "h1. Gollum", commit)
@wiki.update_page(page, 'Smeagol', :textile, "h1. Gollum", commit_details)
assert_equal 2, @wiki.repo.commits.size
assert_equal :textile, @wiki.page("Smeagol").format
@@ -144,17 +183,13 @@ context "Wiki page writing" do
end
test "update nested page with format change" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
index = @wiki.repo.index
index.add("lotr/Gollum.md", "# Gollum")
index.commit("Add nested page")
page = @wiki.page("Gollum")
assert_equal :markdown, @wiki.page("Gollum").format
@wiki.update_page(page, page.name, :textile, "h1. Gollum", commit)
@wiki.update_page(page, page.name, :textile, "h1. Gollum", commit_details)
page = @wiki.page("Gollum")
assert_equal "lotr/Gollum.textile", page.path
@@ -163,23 +198,16 @@ context "Wiki page writing" do
end
test "delete root page" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
@wiki.write_page("Gollum", :markdown, "# Gollum", commit)
@wiki.write_page("Gollum", :markdown, "# Gollum", commit_details)
page = @wiki.page("Gollum")
@wiki.delete_page(page, commit)
@wiki.delete_page(page, commit_details)
assert_equal 2, @wiki.repo.commits.size
assert_nil @wiki.page("Gollum")
end
test "delete nested page" do
commit = { :message => "Gollum page",
:name => "Tom Preston-Werner",
:email => "tom@github.com" }
index = @wiki.repo.index
index.add("greek/Bilbo-Baggins.md", "hi")
index.add("Gollum.md", "hi")
@@ -187,7 +215,7 @@ context "Wiki page writing" do
page = @wiki.page("Bilbo-Baggins")
assert page
@wiki.delete_page(page, commit)
@wiki.delete_page(page, commit_details)
assert_equal 2, @wiki.repo.commits.size
assert_nil @wiki.page("Bilbo-Baggins")
@@ -198,4 +226,59 @@ context "Wiki page writing" do
teardown do
FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git]))
end
end
end
context "Wiki sync with working directory" do
setup do
@path = testpath('examples/wdtest')
Grit::Repo.init(@path)
@wiki = Gollum::Wiki.new(@path)
end
test "write a page" do
@wiki.write_page("New Page", :markdown, "Hi", commit_details)
assert_equal "Hi", File.read(File.join(@path, "New-Page.md"))
end
test "update a page with same name and format" do
@wiki.write_page("New Page", :markdown, "Hi", commit_details)
page = @wiki.page("New Page")
@wiki.update_page(page, page.name, page.format, "Bye", commit_details)
assert_equal "Bye", File.read(File.join(@path, "New-Page.md"))
end
test "update a page with different name and same format" do
@wiki.write_page("New Page", :markdown, "Hi", commit_details)
page = @wiki.page("New Page")
@wiki.update_page(page, "New Page 2", page.format, "Bye", commit_details)
assert_equal "Bye", File.read(File.join(@path, "New-Page-2.md"))
assert !File.exist?(File.join(@path, "New-Page.md"))
end
test "update a page with same name and different format" do
@wiki.write_page("New Page", :markdown, "Hi", commit_details)
page = @wiki.page("New Page")
@wiki.update_page(page, page.name, :textile, "Bye", commit_details)
assert_equal "Bye", File.read(File.join(@path, "New-Page.textile"))
assert !File.exist?(File.join(@path, "New-Page.md"))
end
test "update a page with different name and different format" do
@wiki.write_page("New Page", :markdown, "Hi", commit_details)
page = @wiki.page("New Page")
@wiki.update_page(page, "New Page 2", :textile, "Bye", commit_details)
assert_equal "Bye", File.read(File.join(@path, "New-Page-2.textile"))
assert !File.exist?(File.join(@path, "New-Page.md"))
end
test "delete a page" do
@wiki.write_page("New Page", :markdown, "Hi", commit_details)
page = @wiki.page("New Page")
@wiki.delete_page(page, commit_details)
assert !File.exist?(File.join(@path, "New-Page.md"))
end
teardown do
FileUtils.rm_r(@path)
end
end